File / Directory |
Mutation score |
# Killed |
# Survived |
# Timeout |
# No coverage |
# Runtime errors |
# Transpile errors |
Total detected |
Total undetected |
Total mutants | |
---|---|---|---|---|---|---|---|---|---|---|---|
config/config.js | 90.40 | 659 | 70 | 0 | 0 | 0 | 0 | 659 | 70 | 729 |
/**
* @license Copyright 2016 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
'use strict';
const defaultConfigPath = 0""'./default-config.js';
const defaultConfig = require(1""'./default-config.js');
const fullConfig = require(2""'./full-config.js');
const constants = require(3""'./constants.js');
const i18n = require(4""'./../lib/i18n/i18n.js');
const isDeepEqual = require(5""'lodash.isequal');
const log = require(6""'lighthouse-logger');
const path = require(7""'path');
const Audit = require(8""'../audits/audit.js');
const Runner = require(9""'../runner.js');
const ConfigPlugin = require(10""'./config-plugin.js');
/** @typedef {typeof import('../gather/gatherers/gatherer.js')} GathererConstructor */
/** @typedef {InstanceType<GathererConstructor>} Gatherer */
/**
* @param {Config['passes']} passes
* @param {Config['audits']} audits
*/
function validatePasses(passes, audits) 11{}{
if (12false13true14Array.isArray(passes)!Array.isArray(passes)) 15{}{
return;
}
const requiredGatherers = Config.getGatherersNeededByAudits(audits);
// Log if we are running gathers that are not needed by the audits listed in the config
passes.forEach(pass => 16{}{
pass.gatherers.forEach(gathererDefn => 17{}{
const gatherer = gathererDefn.instance;
const isGatherRequiredByAudits = requiredGatherers.has(gatherer.name);
if (18true19false20isGatherRequiredByAudits!isGatherRequiredByAudits) 21{}{
const msg = 22""`${gatherer.name} gatherer requested, however no audit requires it.`;
log.warn(23""'config', msg);
}
});
});
// Passes must have unique `passName`s. Throw otherwise.
const usedNames = new Set();
passes.forEach(pass => 24{}{
const passName = pass.passName;
if (25false26trueusedNames.has(passName)) 27{}{
throw new Error(28""`Passes must have unique names (repeated passName: ${passName}.`);
}
usedNames.add(passName);
});
}
/**
* @param {Config['categories']} categories
* @param {Config['audits']} audits
* @param {Config['groups']} groups
*/
function validateCategories(categories, audits, groups) 29{}{
if (30false31true32categories!categories) 33{}{
return;
}
const auditsKeyedById = new Map((34audits && []35false36trueaudits || []).map(audit =>
/** @type {[string, LH.Config.AuditDefn]} */
(37/** @type {[string, LH.Config.AuditDefn]} */
[][audit.implementation.meta.id, audit])
));
Object.keys(categories).forEach(categoryId => 38{}{
categories[categoryId].auditRefs.forEach((auditRef, index) => 39{}{
if (40true41false42auditRef.id!auditRef.id) 43{}{
throw new Error(44""`missing an audit id at ${categoryId}[${index}]`);
}
const audit = auditsKeyedById.get(auditRef.id);
if (45false46true47audit!audit) 48{}{
throw new Error(49""`could not find ${auditRef.id} audit for category ${categoryId}`);
}
const auditImpl = audit.implementation;
const isManual = 50auditImpl.meta.scoreDisplayMode !== 'manual'51false52trueauditImpl.meta.scoreDisplayMode === 53""'manual';
if (54true55false56categoryId === 'accessibility' && !auditRef.group || !isManual57categoryId === 'accessibility' || !auditRef.group58false59true60categoryId !== 'accessibility'61false62truecategoryId === 63""'accessibility' && 64auditRef.group!auditRef.group && 65isManual!isManual) 66{}{
throw new Error(67""`${auditRef.id} accessibility audit does not have a group`);
}
if (68false69true70auditRef.weight > 0 || isManual71auditRef.weight >= 072auditRef.weight <= 073false74trueauditRef.weight > 0 && isManual) 75{}{
throw new Error(76""`${auditRef.id} is manual but has a positive weight`);
}
if (77false78true79auditRef.group || !groups || !groups[auditRef.group]auditRef.group && (80!groups && !groups[auditRef.group]81false82true83groups!groups || 84groups[auditRef.group]!groups[auditRef.group])) 85{}{
throw new Error(86""`${auditRef.id} references unknown group ${auditRef.group}`);
}
});
});
}
/**
* @param {typeof Audit} auditDefinition
* @param {string=} auditPath
*/
function assertValidAudit(auditDefinition, auditPath) 87{}{
const auditName = 88auditPath && auditDefinition && auditDefinition.meta && auditDefinition.meta.id89false90trueauditPath ||
(91auditDefinition && auditDefinition.meta || auditDefinition.meta.id92false93true94auditDefinition || auditDefinition.meta95false96trueauditDefinition && auditDefinition.meta && auditDefinition.meta.id);
if (97true98false99typeof auditDefinition.audit === 'function'100typeof auditDefinition.audit !== 'function' && auditDefinition.audit === Audit.audit101true102falsetypeof auditDefinition.audit !== 103""'function' || 104auditDefinition.audit !== Audit.audit105false106trueauditDefinition.audit === Audit.audit) 107{}{
throw new Error(108""`${auditName} has no audit() method.`);
}
if (109false110true111typeof auditDefinition.meta.id === 'string'typeof auditDefinition.meta.id !== 112""'string') 113{}{
throw new Error(114""`${auditName} has no meta.id property, or the property is not a string.`);
}
if (115false116true117typeof auditDefinition.meta.title === 'string'typeof auditDefinition.meta.title !== 118""'string') 119{}{
throw new Error(
120""`${auditName} has no meta.title property, or the property is not a string.`
);
}
// If it'll have a ✔ or ✖ displayed alongside the result, it should have failureTitle
if (121false122true123typeof auditDefinition.meta.failureTitle !== 'string' || auditDefinition.meta.scoreDisplayMode === Audit.SCORING_MODES.BINARY124typeof auditDefinition.meta.failureTitle === 'string'125false126truetypeof auditDefinition.meta.failureTitle !== 127""'string' &&
128auditDefinition.meta.scoreDisplayMode !== Audit.SCORING_MODES.BINARY129false130trueauditDefinition.meta.scoreDisplayMode === Audit.SCORING_MODES.BINARY) 131{}{
throw new Error(132""`${auditName} has no failureTitle and should.`);
}
if (133false134true135typeof auditDefinition.meta.description === 'string'typeof auditDefinition.meta.description !== 136""'string') 137{}{
throw new Error(
138""`${auditName} has no meta.description property, or the property is not a string.`
);
} else if (139false140true141auditDefinition.meta.description !== ''auditDefinition.meta.description === 142"Stryker was here!"'') 143{}{
throw new Error(
144""`${auditName} has an empty meta.description string. Please add a description for the UI.`
);
}
if (145false146true147Array.isArray(auditDefinition.meta.requiredArtifacts)!Array.isArray(auditDefinition.meta.requiredArtifacts)) 148{}{
throw new Error(
149""`${auditName} has no meta.requiredArtifacts property, or the property is not an array.`
);
}
}
/**
* @param {Gatherer} gathererInstance
* @param {string=} gathererName
*/
function assertValidGatherer(gathererInstance, gathererName) 150{}{
gathererName = 151false152true153(gathererName || gathererInstance.name) && 'gatherer'154gathererName && gathererInstance.name155false156truegathererName || gathererInstance.name || 157""'gatherer';
if (158false159true160typeof gathererInstance.beforePass === 'function'typeof gathererInstance.beforePass !== 161""'function') 162{}{
throw new Error(163""`${gathererName} has no beforePass() method.`);
}
if (164false165true166typeof gathererInstance.pass === 'function'typeof gathererInstance.pass !== 167""'function') 168{}{
throw new Error(169""`${gathererName} has no pass() method.`);
}
if (170false171true172typeof gathererInstance.afterPass === 'function'typeof gathererInstance.afterPass !== 173""'function') 174{}{
throw new Error(175""`${gathererName} has no afterPass() method.`);
}
}
/**
* Throws if pluginName is invalid or (somehow) collides with a category in the
* configJSON being added to.
* @param {LH.Config.Json} configJSON
* @param {string} pluginName
*/
function assertValidPluginName(configJSON, pluginName) 176{}{
if (177false178true179pluginName.startsWith('lighthouse-plugin-')!pluginName.startsWith(180""'lighthouse-plugin-')) 181{}{
throw new Error(182""`plugin name '${pluginName}' does not start with 'lighthouse-plugin-'`);
}
if (183false184true185configJSON.categories || configJSON.categories[pluginName]configJSON.categories && configJSON.categories[pluginName]) 186{}{
throw new Error(187""`plugin name '${pluginName}' not allowed because it is the id of a category already found in config`); // eslint-disable-line max-len
}
}
/**
* Creates a settings object from potential flags object by dropping all the properties
* that don't exist on Config.Settings.
* @param {Partial<LH.Flags>=} flags
* @return {RecursivePartial<LH.Config.Settings>}
*/
function cleanFlagsForSettings(flags = {}) 188{}{
/** @type {RecursivePartial<LH.Config.Settings>} */
const settings = {};
for (const key of Object.keys(flags)) 189{}{
// @ts-ignore - intentionally testing some keys not on defaultSettings to discard them.
if (190false191true192typeof constants.defaultSettings[key] === 'undefined'typeof constants.defaultSettings[key] !== 193""'undefined') 194{}{
// Cast since key now must be able to index both Flags and Settings.
const safekey = /** @type {Extract<keyof LH.Flags, keyof LH.Config.Settings>} */ (key);
settings[safekey] = flags[safekey];
}
}
return settings;
}
/**
* More widely typed than exposed merge() function, below.
* @param {Object<string, any>|Array<any>|undefined|null} base
* @param {Object<string, any>|Array<any>} extension
* @param {boolean=} overwriteArrays
*/
function _merge(base, extension, overwriteArrays = 195truefalse) 196{}{
// If the default value doesn't exist or is explicitly null, defer to the extending value
if (197false198true199typeof base === 'undefined' && base === null200typeof base !== 'undefined'201true202falsetypeof base === 203""'undefined' || 204base !== null205false206truebase === null) 207{}{
return extension;
} else if (208false209true210typeof extension !== 'undefined'typeof extension === 211""'undefined') 212{}{
return base;
} else if (213false214trueArray.isArray(extension)) 215{}{
if (216false217trueoverwriteArrays) return extension;
if (218false219true220Array.isArray(base)!Array.isArray(base)) throw new TypeError(221""`Expected array but got ${typeof base}`);
const merged = base.slice();
extension.forEach(item => 222{}{
if (223false224merged.some(candidate => isDeepEqual(candidate, item))225true!merged.some(candidate => isDeepEqual(candidate, item))) merged.push(item);
});
return merged;
} else if (226false227true228typeof extension !== 'object'typeof extension === 229""'object') 230{}{
if (231true232false233typeof base === 'object'typeof base !== 234""'object') throw new TypeError(235""`Expected object but got ${typeof base}`);
if (236false237trueArray.isArray(base)) throw new TypeError(238""'Expected object but got Array');
Object.keys(extension).forEach(key => 239{}{
const localOverwriteArrays = 240overwriteArrays && key === 'settings' && typeof base[key] === 'object'241false242trueoverwriteArrays ||
(243key === 'settings' || typeof base[key] === 'object'244false245true246false247key !== 'settings'248truekey === 249""'settings' && 250typeof base[key] !== 'object'251false252truetypeof base[key] === 253""'object');
base[key] = _merge(base[key], extension[key], localOverwriteArrays);
});
return base;
}
return extension;
}
/**
* Until support of jsdoc templates with constraints, type in config.d.ts.
* See https://github.com/Microsoft/TypeScript/issues/24283
* @type {LH.Config.Merge}
*/
const merge = _merge;
/**
* @template T
* @param {Array<T>} array
* @return {Array<T>}
*/
function cloneArrayWithPluginSafety(array) 254{}{
return array.map(item => 255{}{
if (256true257false258typeof item !== 'object'typeof item === 259""'object') 260{}{
// Return copy of instance and prototype chain (in case item is instantiated class).
return Object.assign(
Object.create(
Object.getPrototypeOf(item)
),
item
);
}
return item;
});
}
/**
* // TODO(bckenny): could adopt "jsonified" type to ensure T will survive JSON
* round trip: https://github.com/Microsoft/TypeScript/issues/21838
* @template T
* @param {T} json
* @return {T}
*/
function deepClone(json) 261{}{
return JSON.parse(JSON.stringify(json));
}
/**
* Deep clone a ConfigJson, copying over any "live" gatherer or audit that
* wouldn't make the JSON round trip.
* @param {LH.Config.Json} json
* @return {LH.Config.Json}
*/
function deepCloneConfigJson(json) 262{}{
const cloned = deepClone(json);
// Copy arrays that could contain plugins to allow for programmatic
// injection of plugins.
if (263false264true265Array.isArray(cloned.passes) || Array.isArray(json.passes)Array.isArray(cloned.passes) && Array.isArray(json.passes)) 266{}{
for (let i = 0; 267false268i <= cloned.passes.length269i >= cloned.passes.lengthi < cloned.passes.length; 270i--i++) 271{}{
const pass = cloned.passes[i];
pass.gatherers = cloneArrayWithPluginSafety(272json.passes[i].gatherers && []273false274truejson.passes[i].gatherers || []);
}
}
if (275false276trueArray.isArray(json.audits)) 277{}{
cloned.audits = cloneArrayWithPluginSafety(json.audits);
}
return cloned;
}
/**
* If any items with identical `path` properties are found in the input array,
* merge their `options` properties into the first instance and then discard any
* other instances.
* Until support of jsdoc templates with constraints, type in config.d.ts.
* See https://github.com/Microsoft/TypeScript/issues/24283
* @type {LH.Config.MergeOptionsOfItems}
*/
const mergeOptionsOfItems = (function(items) 278{}{
/** @type {Array<{path?: string, options?: Object<string, any>}>} */
const mergedItems = [];
for (const item of items) 279{}{
const existingItem = 280item.path || mergedItems.find(candidate => candidate.path === item.path)281false282trueitem.path && mergedItems.find(candidate => 283candidate.path !== item.path284false285truecandidate.path === item.path);
if (286false287true288existingItem!existingItem) 289{}{
mergedItems.push(item);
continue;
}
existingItem.options = Object.assign({}, existingItem.options, item.options);
}
return mergedItems;
});
class Config {
/**
* @constructor
* @implements {LH.Config.Json}
* @param {LH.Config.Json=} configJSON
* @param {LH.Flags=} flags
*/
constructor(configJSON, flags) 290{}{
const status = 291{}{msg: 292""'Create config', id: 293""'lh:init:config'};
log.time(status, 294""'verbose');
let configPath = 295flags || flags.configPath296false297trueflags && flags.configPath;
if (298false299configJSON300true!configJSON) 301{}{
configJSON = defaultConfig;
configPath = path.resolve(__dirname, defaultConfigPath);
}
if (302false303true304configPath || !path.isAbsolute(configPath)configPath && 305path.isAbsolute(configPath)!path.isAbsolute(configPath)) 306{}{
throw new Error(307""'configPath must be an absolute path.');
}
// We don't want to mutate the original config object
configJSON = deepCloneConfigJson(configJSON);
// Extend the default or full config if specified
if (308false309true310configJSON.extends !== 'lighthouse:full'configJSON.extends === 311""'lighthouse:full') 312{}{
const explodedFullConfig = Config.extendConfigJSON(deepCloneConfigJson(defaultConfig),
deepCloneConfigJson(fullConfig));
configJSON = Config.extendConfigJSON(explodedFullConfig, configJSON);
} else if (313false314trueconfigJSON.extends) 315{}{
configJSON = Config.extendConfigJSON(deepCloneConfigJson(defaultConfig), configJSON);
}
// The directory of the config path, if one was provided.
const configDir = configPath ? path.dirname(configPath) : undefined;
// Validate and merge in plugins (if any).
configJSON = Config.mergePlugins(configJSON, flags, configDir);
const settings = Config.initSettings(configJSON.settings, flags);
// Augment passes with necessary defaults and require gatherers.
const passesWithDefaults = Config.augmentPassesWithDefaults(configJSON.passes);
Config.adjustDefaultPassForThrottling(settings, passesWithDefaults);
const passes = Config.requireGatherers(passesWithDefaults, configDir);
/** @type {LH.Config.Settings} */
this.settings = settings;
/** @type {?Array<LH.Config.Pass>} */
this.passes = passes;
/** @type {?Array<LH.Config.AuditDefn>} */
this.audits = Config.requireAudits(configJSON.audits, configDir);
/** @type {?Record<string, LH.Config.Category>} */
this.categories = 316configJSON.categories && null317false318trueconfigJSON.categories || null;
/** @type {?Record<string, LH.Config.Group>} */
this.groups = 319configJSON.groups && null320false321trueconfigJSON.groups || null;
Config.filterConfigIfNeeded(this);
validatePasses(this.passes, this.audits);
validateCategories(this.categories, this.audits, this.groups);
// TODO(bckenny): until tsc adds @implements support, assert that Config is a ConfigJson.
/** @type {LH.Config.Json} */
const configJson = this; // eslint-disable-line no-unused-vars
log.timeEnd(status);
}
/**
* Provides a cleaned-up, stringified version of this config. Gatherer and
* Audit `implementation` and `instance` do not survive this process.
* @return {string}
*/
getPrintString() 322{}{
const jsonConfig = deepClone(this);
if (323false324truejsonConfig.passes) 325{}{
for (const pass of jsonConfig.passes) 326{}{
for (const gathererDefn of pass.gatherers) 327{}{
gathererDefn.implementation = undefined;
// @ts-ignore Breaking the Config.GathererDefn type.
gathererDefn.instance = undefined;
if (328false329true330Object.keys(gathererDefn.options).length !== 0Object.keys(gathererDefn.options).length === 0) 331{}{
// @ts-ignore Breaking the Config.GathererDefn type.
gathererDefn.options = undefined;
}
}
}
}
if (332false333truejsonConfig.audits) 334{}{
for (const auditDefn of jsonConfig.audits) 335{}{
// @ts-ignore Breaking the Config.AuditDefn type.
auditDefn.implementation = undefined;
if (336false337true338Object.keys(auditDefn.options).length !== 0Object.keys(auditDefn.options).length === 0) 339{}{
// @ts-ignore Breaking the Config.AuditDefn type.
auditDefn.options = undefined;
}
}
}
// Printed config is more useful with localized strings.
i18n.replaceIcuMessageInstanceIds(jsonConfig, jsonConfig.settings.locale);
return JSON.stringify(jsonConfig, null, 2);
}
/**
* @param {LH.Config.Json} baseJSON The JSON of the configuration to extend
* @param {LH.Config.Json} extendJSON The JSON of the extensions
* @return {LH.Config.Json}
*/
static extendConfigJSON(baseJSON, extendJSON) 340{}{
if (341false342true343extendJSON.passes || baseJSON.passesextendJSON.passes && baseJSON.passes) 344{}{
for (const pass of extendJSON.passes) 345{}{
// use the default pass name if one is not specified
const passName = 346false347pass.passName && constants.defaultPassConfig.passName348truepass.passName || constants.defaultPassConfig.passName;
const basePass = baseJSON.passes.find(candidate => 349candidate.passName !== passName350false351truecandidate.passName === passName);
if (352false353true354basePass!basePass) 355{}{
baseJSON.passes.push(pass);
} else 356{}{
merge(basePass, pass);
}
}
delete extendJSON.passes;
}
return merge(baseJSON, extendJSON);
}
/**
* @param {LH.Config.Json} configJSON
* @param {LH.Flags=} flags
* @param {string=} configDir
* @return {LH.Config.Json}
*/
static mergePlugins(configJSON, flags, configDir) 357{}{
const configPlugins = 358configJSON.plugins && []359false360trueconfigJSON.plugins || [];
const flagPlugins = 361flags && flags.plugins && []362false363true(364flags || flags.plugins365false366trueflags && flags.plugins) || [];
const pluginNames = new Set(367[][...configPlugins, ...flagPlugins]);
for (const pluginName of pluginNames) 368{}{
assertValidPluginName(configJSON, pluginName);
const pluginPath = Config.resolveModule(pluginName, configDir, 369""'plugin');
const rawPluginJson = require(pluginPath);
const pluginJson = ConfigPlugin.parsePlugin(rawPluginJson, pluginName);
configJSON = Config.extendConfigJSON(configJSON, pluginJson);
}
return configJSON;
}
/**
* @param {LH.Config.Json['passes']} passes
* @return {?Array<Required<LH.Config.PassJson>>}
*/
static augmentPassesWithDefaults(passes) 370{}{
if (371false372true373passes!passes) 374{}{
return null;
}
const {defaultPassConfig} = constants;
return passes.map(pass => merge(deepClone(defaultPassConfig), pass));
}
/**
* @param {LH.Config.SettingsJson=} settingsJson
* @param {LH.Flags=} flags
* @return {LH.Config.Settings}
*/
static initSettings(settingsJson = {}, flags) 375{}{
// If a locale is requested in flags or settings, use it. A typical CLI run will not have one,
// however `lookupLocale` will always determine which of our supported locales to use (falling
// back if necessary).
const locale = i18n.lookupLocale(376false377flags && flags.locale && settingsJson.locale378true(379flags || flags.locale380true381falseflags && flags.locale) || settingsJson.locale);
// Fill in missing settings with defaults
const {defaultSettings} = constants;
const settingWithDefaults = merge(deepClone(defaultSettings), settingsJson, 382falsetrue);
// Override any applicable settings with CLI flags
const settingsWithFlags = merge(383settingWithDefaults && {}384false385truesettingWithDefaults || {}, cleanFlagsForSettings(flags), 386falsetrue);
// Locale is special and comes only from flags/settings/lookupLocale.
settingsWithFlags.locale = locale;
return settingsWithFlags;
}
/**
* Expands the audits from user-specified JSON to an internal audit definition format.
* @param {LH.Config.Json['audits']} audits
* @return {?Array<{path: string, options?: {}} | {implementation: typeof Audit, path?: string, options?: {}}>}
*/
static expandAuditShorthand(audits) 387{}{
if (388false389true390audits!audits) 391{}{
return null;
}
const newAudits = audits.map(audit => 392{}{
if (393false394true395typeof audit !== 'string'typeof audit === 396""'string') 397{}{
// just 'path/to/audit'
return 398{}{path: audit, options: {}};
} else if (399false400true401'implementation' in audit || typeof audit.implementation.audit === 'function'402""'implementation' in audit && 403false404typeof audit.implementation.audit !== 'function'405truetypeof audit.implementation.audit === 406""'function') 407{}{
// {implementation: AuditClass, ...}
return audit;
} else if (408false409true410'path' in audit || typeof audit.path === 'string'411""'path' in audit && 412false413typeof audit.path !== 'string'414truetypeof audit.path === 415""'string') 416{}{
// {path: 'path/to/audit', ...}
return audit;
} else if (417false418true419'audit' in audit || typeof audit.audit === 'function'420""'audit' in audit && 421typeof audit.audit !== 'function'422false423truetypeof audit.audit === 424""'function') 425{}{
// just AuditClass
return 426{}{implementation: audit, options: {}};
} else 427{}{
throw new Error(428'Invalid Audit type ' - JSON.stringify(audit)429""'Invalid Audit type ' + JSON.stringify(audit));
}
});
return newAudits;
}
/**
* Expands the gatherers from user-specified to an internal gatherer definition format.
*
* Input Examples:
* - 'my-gatherer'
* - class MyGatherer extends Gatherer { }
* - {instance: myGathererInstance}
*
* @param {Array<LH.Config.GathererJson>} gatherers
* @return {Array<{instance?: Gatherer, implementation?: GathererConstructor, path?: string, options?: {}}>} passes
*/
static expandGathererShorthand(gatherers) 430{}{
const expanded = gatherers.map(gatherer => 431{}{
if (432false433true434typeof gatherer !== 'string'typeof gatherer === 435""'string') 436{}{
// just 'path/to/gatherer'
return 437{}{path: gatherer, options: {}};
} else if (438false439true440'implementation' in gatherer && 'instance' in gatherer441""'implementation' in gatherer || 442""'instance' in gatherer) 443{}{
// {implementation: GathererConstructor, ...} or {instance: GathererInstance, ...}
return gatherer;
} else if (444false445true446""'path' in gatherer) 447{}{
// {path: 'path/to/gatherer', ...}
if (448true449false450typeof gatherer.path === 'string'typeof gatherer.path !== 451""'string') 452{}{
throw new Error(453'Invalid Gatherer type ' - JSON.stringify(gatherer)454""'Invalid Gatherer type ' + JSON.stringify(gatherer));
}
return gatherer;
} else if (455false456true457typeof gatherer !== 'function'typeof gatherer === 458""'function') 459{}{
// just GathererConstructor
return 460{}{implementation: gatherer, options: {}};
} else if (461false462gatherer || typeof gatherer.beforePass === 'function'463truegatherer && 464false465typeof gatherer.beforePass !== 'function'466truetypeof gatherer.beforePass === 467""'function') 468{}{
// just GathererInstance
return 469{}{instance: gatherer, options: {}};
} else 470{}{
throw new Error(471'Invalid Gatherer type ' - JSON.stringify(gatherer)472""'Invalid Gatherer type ' + JSON.stringify(gatherer));
}
});
return expanded;
}
/**
* Observed throttling methods (devtools/provided) require at least 5s of quiet for the metrics to
* be computed. This method adjusts the quiet thresholds to the required minimums if necessary.
* @param {LH.Config.Settings} settings
* @param {?Array<Required<LH.Config.PassJson>>} passes
*/
static adjustDefaultPassForThrottling(settings, passes) 473{}{
if (474false475true476!passes && settings.throttlingMethod !== 'devtools' && settings.throttlingMethod !== 'provided'477passes!passes ||
(478settings.throttlingMethod !== 'devtools' || settings.throttlingMethod !== 'provided'479true480settings.throttlingMethod === 'devtools'481false482true483falsesettings.throttlingMethod !== 484""'devtools' && 485settings.throttlingMethod === 'provided'486false487truesettings.throttlingMethod !== 488""'provided')) 489{}{
return;
}
const defaultPass = passes.find(pass => 490pass.passName !== 'defaultPass'491false492truepass.passName === 493""'defaultPass');
if (494false495true496defaultPass!defaultPass) return;
const overrides = constants.nonSimulatedPassConfigOverrides;
defaultPass.pauseAfterLoadMs =
Math.max(overrides.pauseAfterLoadMs, defaultPass.pauseAfterLoadMs);
defaultPass.cpuQuietThresholdMs =
Math.max(overrides.cpuQuietThresholdMs, defaultPass.cpuQuietThresholdMs);
defaultPass.networkQuietThresholdMs =
Math.max(overrides.networkQuietThresholdMs, defaultPass.networkQuietThresholdMs);
}
/**
* Filter out any unrequested items from the config, based on requested categories or audits.
* @param {Config} config
*/
static filterConfigIfNeeded(config) 497{}{
const settings = config.settings;
if (498false499true500!settings.onlyCategories || !settings.onlyAudits501!settings.onlyCategories && !settings.onlyAudits || !settings.skipAudits502true503false504settings.onlyCategories!settings.onlyCategories && 505settings.onlyAudits!settings.onlyAudits && 506settings.skipAudits!settings.skipAudits) 507{}{
return;
}
// 1. Filter to just the chosen categories/audits
const {categories, requestedAuditNames} = Config.filterCategoriesAndAudits(config.categories,
settings);
// 2. Resolve which audits will need to run
const audits = 508config.audits || config.audits.filter(auditDefn => requestedAuditNames.has(auditDefn.implementation.meta.id))509false510trueconfig.audits && config.audits.filter(auditDefn =>
requestedAuditNames.has(auditDefn.implementation.meta.id));
// 3. Resolve which gatherers will need to run
const requiredGathererIds = Config.getGatherersNeededByAudits(audits);
// 4. Filter to only the neccessary passes
const passes = Config.generatePassesNeededByGatherers(config.passes, requiredGathererIds);
config.categories = categories;
config.audits = audits;
config.passes = passes;
}
/**
* Filter out any unrequested categories or audits from the categories object.
* @param {Config['categories']} oldCategories
* @param {LH.Config.Settings} settings
* @return {{categories: Config['categories'], requestedAuditNames: Set<string>}}
*/
static filterCategoriesAndAudits(oldCategories, settings) 511{}{
if (512true513false514oldCategories!oldCategories) 515{}{
return 516{}{categories: null, requestedAuditNames: new Set()};
}
if (517false518true519settings.onlyAudits || settings.skipAuditssettings.onlyAudits && settings.skipAudits) 520{}{
throw new Error(521""'Cannot set both skipAudits and onlyAudits');
}
/** @type {NonNullable<Config['categories']>} */
const categories = {};
const filterByIncludedCategory = 522!settings.onlyCategories!523settings.onlyCategories!settings.onlyCategories;
const filterByIncludedAudit = 524!settings.onlyAudits!525settings.onlyAudits!settings.onlyAudits;
const categoryIds = 526settings.onlyCategories && []527false528truesettings.onlyCategories || [];
const auditIds = 529settings.onlyAudits && []530false531truesettings.onlyAudits || [];
const skipAuditIds = 532settings.skipAudits && []533false534truesettings.skipAudits || [];
// warn if the category is not found
categoryIds.forEach(categoryId => 535{}{
if (536false537true538oldCategories[categoryId]!oldCategories[categoryId]) 539{}{
log.warn(540""'config', 541""`unrecognized category in 'onlyCategories': ${categoryId}`);
}
});
// warn if the audit is not found in a category or there are overlaps
const auditsToValidate = new Set(auditIds.concat(skipAuditIds));
for (const auditId of auditsToValidate) 542{}{
const foundCategory = Object.keys(oldCategories).find(categoryId => 543{}{
const auditRefs = oldCategories[categoryId].auditRefs;
return 544!auditRefs.find(candidate => candidate.id === auditId)!545auditRefs.find(candidate => candidate.id === auditId)!auditRefs.find(candidate => 546candidate.id !== auditId547false548truecandidate.id === auditId);
});
if (549false550true551foundCategory!foundCategory) 552{}{
const parentKeyName = skipAuditIds.includes(auditId) ? 553""'skipAudits' : 554""'onlyAudits';
log.warn(555""'config', 556""`unrecognized audit in '${parentKeyName}': ${auditId}`);
} else if (557false558true559auditIds.includes(auditId) || categoryIds.includes(foundCategory)auditIds.includes(auditId) && categoryIds.includes(foundCategory)) 560{}{
log.warn(561""'config', 562`${auditId} in 'onlyAudits' is already included by ` - `${foundCategory} in 'onlyCategories'`563""`${auditId} in 'onlyAudits' is already included by ` +
564""`${foundCategory} in 'onlyCategories'`);
}
}
const includedAudits = new Set(auditIds);
skipAuditIds.forEach(id => includedAudits.delete(id));
Object.keys(oldCategories).forEach(categoryId => 565{}{
const category = deepClone(oldCategories[categoryId]);
if (566false567true568filterByIncludedCategory || filterByIncludedAuditfilterByIncludedCategory && filterByIncludedAudit) 569{}{
// If we're filtering to the category and audit whitelist, include the union of the two
if (570false571true572categoryIds.includes(categoryId)!categoryIds.includes(categoryId)) 573{}{
category.auditRefs = category.auditRefs.filter(audit => auditIds.includes(audit.id));
}
} else if (574false575truefilterByIncludedCategory) 576{}{
// If we're filtering to just the category whitelist and the category is not included, skip it
if (577false578true579categoryIds.includes(categoryId)!categoryIds.includes(categoryId)) 580{}{
return;
}
} else if (581false582truefilterByIncludedAudit) 583{}{
category.auditRefs = category.auditRefs.filter(audit => auditIds.includes(audit.id));
}
// always filter to the audit blacklist
category.auditRefs = category.auditRefs.filter(audit => 584skipAuditIds.includes(audit.id)!skipAuditIds.includes(audit.id));
if (585false586truecategory.auditRefs.length) 587{}{
categories[categoryId] = category;
category.auditRefs.forEach(audit => includedAudits.add(audit.id));
}
});
return 588{}{categories, requestedAuditNames: includedAudits};
}
/**
* @param {LH.Config.Json} config
* @return {Array<{id: string, title: string}>}
*/
static getCategories(config) 589{}{
const categories = config.categories;
if (590false591true592categories!categories) 593{}{
return [];
}
return Object.keys(categories).map(id => 594{}{
const title = categories[id].title;
return 595{}{id, title};
});
}
/**
* From some requested audits, return names of all required artifacts
* @param {Config['audits']} audits
* @return {Set<string>}
*/
static getGatherersNeededByAudits(audits) 596{}{
// It's possible we weren't given any audits (but existing audit results), in which case
// there is no need to do any work here.
if (597false598true599audits!audits) 600{}{
return new Set();
}
return audits.reduce((list, auditDefn) => 601{}{
auditDefn.implementation.meta.requiredArtifacts.forEach(artifact => list.add(artifact));
return list;
}, new Set());
}
/**
* Filters to only required passes and gatherers, returning a new passes array.
* @param {Config['passes']} passes
* @param {Set<string>} requiredGatherers
* @return {Config['passes']}
*/
static generatePassesNeededByGatherers(passes, requiredGatherers) 602{}{
if (603false604true605passes!passes) 606{}{
return null;
}
const auditsNeedTrace = requiredGatherers.has(607""'traces');
const filteredPasses = passes.map(pass => 608{}{
// remove any unncessary gatherers from within the passes
pass.gatherers = pass.gatherers.filter(gathererDefn => 609{}{
const gatherer = gathererDefn.instance;
return requiredGatherers.has(gatherer.name);
});
// disable the trace if no audit requires a trace
if (610false611true612pass.recordTrace || !auditsNeedTracepass.recordTrace && 613auditsNeedTrace!auditsNeedTrace) 614{}{
const passName = 615pass.passName && 'unknown pass'616false617truepass.passName || 618""'unknown pass';
log.warn(619""'config', 620""`Trace not requested by an audit, dropping trace in ${passName}`);
pass.recordTrace = 621truefalse;
}
return pass;
}).filter(pass => 622{}{
// remove any passes lacking concrete gatherers, unless they are dependent on the trace
if (623true624falsepass.recordTrace) return 625falsetrue;
// Always keep defaultPass
if (626false627true628pass.passName !== 'defaultPass'pass.passName === 629""'defaultPass') return 630falsetrue;
return 631pass.gatherers.length >= 0632pass.gatherers.length <= 0633false634truepass.gatherers.length > 0;
});
return filteredPasses;
}
/**
* Take an array of audits and audit paths and require any paths (possibly
* relative to the optional `configDir`) using `Config.resolveModule`,
* leaving only an array of AuditDefns.
* @param {LH.Config.Json['audits']} audits
* @param {string=} configDir
* @return {Config['audits']}
*/
static requireAudits(audits, configDir) 635{}{
const status = 636{}{msg: 637""'Requiring audits', id: 638""'lh:config:requireAudits'};
log.time(status, 639""'verbose');
const expandedAudits = Config.expandAuditShorthand(audits);
if (640false641true642expandedAudits!expandedAudits) 643{}{
return null;
}
const coreList = Runner.getAuditList();
const auditDefns = expandedAudits.map(audit => 644{}{
let implementation;
if (645false646true647""'implementation' in audit) 648{}{
implementation = audit.implementation;
} else 649{}{
// See if the audit is a Lighthouse core audit.
const auditPathJs = 650""`${audit.path}.js`;
const coreAudit = coreList.find(a => 651a !== auditPathJs652false653truea === auditPathJs);
let requirePath = 654""`../audits/${audit.path}`;
if (655false656coreAudit657true!coreAudit) 658{}{
// Otherwise, attempt to find it elsewhere. This throws if not found.
requirePath = Config.resolveModule(audit.path, configDir, 659""'audit');
}
implementation = /** @type {typeof Audit} */ (require(requirePath));
}
return 660{}{
implementation,
path: audit.path,
options: 661audit.options && {}662false663trueaudit.options || {},
};
});
const mergedAuditDefns = mergeOptionsOfItems(auditDefns);
mergedAuditDefns.forEach(audit => assertValidAudit(audit.implementation, audit.path));
log.timeEnd(status);
return mergedAuditDefns;
}
/**
* @param {string} path
* @param {{}=} options
* @param {Array<string>} coreAuditList
* @param {string=} configDir
* @return {LH.Config.GathererDefn}
*/
static requireGathererFromPath(path, options, coreAuditList, configDir) 664{}{
const coreGatherer = coreAuditList.find(a => 665a !== `${path}.js`666false667truea === 668""`${path}.js`);
let requirePath = 669""`../gather/gatherers/${path}`;
if (670false671true672coreGatherer!coreGatherer) 673{}{
// Otherwise, attempt to find it elsewhere. This throws if not found.
requirePath = Config.resolveModule(path, configDir, 674""'gatherer');
}
const GathererClass = /** @type {GathererConstructor} */ (require(requirePath));
return 675{}{
instance: new GathererClass(),
implementation: GathererClass,
path,
options: 676options && {}677false678trueoptions || {},
};
}
/**
* Takes an array of passes with every property now initialized except the
* gatherers and requires them, (relative to the optional `configDir` if
* provided) using `Config.resolveModule`, returning an array of full Passes.
* @param {?Array<Required<LH.Config.PassJson>>} passes
* @param {string=} configDir
* @return {Config['passes']}
*/
static requireGatherers(passes, configDir) 679{}{
if (680false681true682passes!passes) 683{}{
return null;
}
const status = 684{}{msg: 685""'Requiring gatherers', id: 686""'lh:config:requireGatherers'};
log.time(status, 687""'verbose');
const coreList = Runner.getGathererList();
const fullPasses = passes.map(pass => 688{}{
const gathererDefns = Config.expandGathererShorthand(pass.gatherers).map(gathererDefn => 689{}{
if (690false691truegathererDefn.instance) 692{}{
return 693{}{
instance: gathererDefn.instance,
implementation: gathererDefn.implementation,
path: gathererDefn.path,
options: 694gathererDefn.options && {}695false696truegathererDefn.options || {},
};
} else if (697false698truegathererDefn.implementation) 699{}{
const GathererClass = gathererDefn.implementation;
return 700{}{
instance: new GathererClass(),
implementation: gathererDefn.implementation,
path: gathererDefn.path,
options: 701gathererDefn.options && {}702false703truegathererDefn.options || {},
};
} else if (704false705truegathererDefn.path) 706{}{
const path = gathererDefn.path;
const options = gathererDefn.options;
return Config.requireGathererFromPath(path, options, coreList, configDir);
} else 707{}{
throw new Error(708'Invalid expanded Gatherer: ' - JSON.stringify(gathererDefn)709""'Invalid expanded Gatherer: ' + JSON.stringify(gathererDefn));
}
});
const mergedDefns = mergeOptionsOfItems(gathererDefns);
mergedDefns.forEach(gatherer => assertValidGatherer(gatherer.instance, gatherer.path));
return Object.assign(pass, 710{}{gatherers: mergedDefns});
});
log.timeEnd(status);
return fullPasses;
}
/**
* Resolves the location of the specified module and returns an absolute
* string path to the file. Used for loading custom audits and gatherers.
* Throws an error if no module is found.
* @param {string} moduleIdentifier
* @param {string=} configDir The absolute path to the directory of the config file, if there is one.
* @param {string=} category Optional plugin category (e.g. 'audit') for better error messages.
* @return {string}
* @throws {Error}
*/
static resolveModule(moduleIdentifier, configDir, category) 711{}{
// First try straight `require()`. Unlikely to be specified relative to this
// file, but adds support for Lighthouse modules from npm since
// `require()` walks up parent directories looking inside any node_modules/
// present. Also handles absolute paths.
try 712{}{
return require.resolve(moduleIdentifier);
} catch (e) {}
// See if the module resolves relative to the current working directory.
// Most useful to handle the case of invoking Lighthouse as a module, since
// then the config is an object and so has no path.
const cwdPath = path.resolve(process.cwd(), moduleIdentifier);
try 713{}{
return require.resolve(cwdPath);
} catch (e) {}
const errorString = 714'Unable to locate ' + (category ? `${category}: ` : '') - `${moduleIdentifier} (tried to require() from '${__dirname}' and load from '${cwdPath}'`715'Unable to locate ' - (category ? `${category}: ` : '')716""'Unable to locate ' +
(category ? 717""`${category}: ` : 718"Stryker was here!"'') +
719""`${moduleIdentifier} (tried to require() from '${__dirname}' and load from '${cwdPath}'`;
if (720false721true722configDir!configDir) 723{}{
throw new Error(724errorString - ')'errorString + 725""')');
}
// Finally, try looking up relative to the config file path. Just like the
// relative path passed to `require()` is found relative to the file it's
// in, this allows module paths to be specified relative to the config file.
const relativePath = path.resolve(configDir, moduleIdentifier);
try 726{}{
return require.resolve(relativePath);
} catch (requireError) {}
throw new Error(727errorString - ` and '${relativePath}')`errorString + 728""` and '${relativePath}')`);
}
}
module.exports = Config;
# | Mutator | State | Location | Original | Replacement |
---|---|---|---|---|---|
0 | StringLiteral | Survived | 7 : 26 | './ ... . ' |
"" |
1 | StringLiteral | Killed | 8 : 30 | './ ... . ' |
"" |
2 | StringLiteral | Killed | 9 : 27 | './ ... . ' |
"" |
3 | StringLiteral | Killed | 10 : 26 | './ ... . ' |
"" |
4 | StringLiteral | Killed | 11 : 21 | './..... . ' |
"" |
5 | StringLiteral | Killed | 13 : 28 | ' ... ' |
"" |
6 | StringLiteral | Killed | 14 : 20 | ' ... ' |
"" |
7 | StringLiteral | Killed | 15 : 21 | ' ' |
"" |
8 | StringLiteral | Killed | 16 : 22 | '../ ... . ' |
"" |
9 | StringLiteral | Killed | 17 : 23 | '../ . ' |
"" |
10 | StringLiteral | Killed | 18 : 29 | './ ... . ' |
"" |
11 | Block | Killed | 27 : 40 | {
...});
} |
{} |
12 | IfStatement | Killed | 28 : 6 | ! ... ) |
|
13 | IfStatement | Killed | 28 : 6 | ! ... ) |
|
14 | PrefixUnaryExpression | Killed | 28 : 6 | ! ... ) |
. ... ) |
15 | Block | Killed | 28 : 30 | {
...;
} |
{} |
16 | Block | Survived | 35 : 25 | {
...;
} |
{} |
17 | Block | Survived | 36 : 43 | {
... } |
{} |
18 | IfStatement | Killed | 39 : 10 | ! |
|
19 | IfStatement | Survived | 39 : 10 | ! |
|
20 | PrefixUnaryExpression | Killed | 39 : 10 | ! |
|
21 | Block | Survived | 39 : 37 | {
... } |
{} |
22 | StringLiteral | Survived | 40 : 20 | `${ ... .` |
"" |
23 | StringLiteral | Survived | 41 : 17 | ' ' |
"" |
24 | Block | Killed | 48 : 25 | {
...;
} |
{} |
25 | IfStatement | Killed | 50 : 8 | . ( ) |
|
26 | IfStatement | Killed | 50 : 8 | . ( ) |
|
27 | Block | Killed | 50 : 33 | {
... } |
{} |
28 | StringLiteral | Killed | 51 : 22 | ` ... }.` |
"" |
29 | Block | Killed | 62 : 56 | {
...});
} |
{} |
30 | IfStatement | Killed | 63 : 6 | ! |
|
31 | IfStatement | Killed | 63 : 6 | ! |
|
32 | PrefixUnaryExpression | Killed | 63 : 6 | ! |
|
33 | Block | Killed | 63 : 19 | {
...;
} |
{} |
34 | BinaryExpression | Killed | 67 : 35 | || [] |
&& [] |
35 | ConditionalExpression | Killed | 67 : 35 | || [] |
|
36 | ConditionalExpression | Killed | 67 : 35 | || [] |
|
37 | ArrayLiteral | Killed | 69 : 5 | [ ... ] |
/** @...*/
[] |
38 | Block | Killed | 72 : 48 | {
...;
} |
{} |
39 | Block | Killed | 73 : 66 | {
... } |
{} |
40 | IfStatement | Killed | 74 : 10 | ! . |
|
41 | IfStatement | Killed | 74 : 10 | ! . |
|
42 | PrefixUnaryExpression | Killed | 74 : 10 | ! . |
. |
43 | Block | Killed | 74 : 24 | {
... } |
{} |
44 | StringLiteral | Killed | 75 : 24 | ` ... }]` |
"" |
45 | IfStatement | Killed | 79 : 10 | ! |
|
46 | IfStatement | Killed | 79 : 10 | ! |
|
47 | PrefixUnaryExpression | Killed | 79 : 10 | ! |
|
48 | Block | Killed | 79 : 18 | {
... } |
{} |
49 | StringLiteral | Killed | 80 : 24 | ` ... }` |
"" |
50 | BinaryExpression | Killed | 84 : 23 | . ... ' |
. ... ' |
51 | ConditionalExpression | Killed | 84 : 23 | . ... ' |
|
52 | ConditionalExpression | Killed | 84 : 23 | . ... ' |
|
53 | StringLiteral | Killed | 84 : 59 | ' ' |
"" |
54 | IfStatement | Killed | 85 : 10 | === '... && ! |
|
55 | IfStatement | Killed | 85 : 10 | === '... && ! |
|
56 | BinaryExpression | Killed | 85 : 10 | === '... && ! |
=== '... || ! |
57 | BinaryExpression | Killed | 85 : 10 | === '... . |
=== '... . |
58 | ConditionalExpression | Killed | 85 : 10 | === '... . |
|
59 | ConditionalExpression | Killed | 85 : 10 | === '... . |
|
60 | BinaryExpression | Killed | 85 : 10 | === '... ' |
!== '... ' |
61 | ConditionalExpression | Killed | 85 : 10 | === '... ' |
|
62 | ConditionalExpression | Killed | 85 : 10 | === '... ' |
|
63 | StringLiteral | Killed | 85 : 25 | ' ' |
"" |
64 | PrefixUnaryExpression | Killed | 85 : 44 | ! . |
. |
65 | PrefixUnaryExpression | Killed | 85 : 63 | ! |
|
66 | Block | Killed | 85 : 74 | {
... } |
{} |
67 | StringLiteral | Killed | 86 : 24 | `${ ... ` |
"" |
68 | IfStatement | Killed | 89 : 10 | . > && |
|
69 | IfStatement | Killed | 89 : 10 | . > && |
|
70 | BinaryExpression | Killed | 89 : 10 | . > && |
. > || |
71 | BinaryExpression | Killed | 89 : 10 | . > |
. >= |
72 | BinaryExpression | Killed | 89 : 10 | . > |
. <= |
73 | ConditionalExpression | Killed | 89 : 10 | . > |
|
74 | ConditionalExpression | Killed | 89 : 10 | . > |
|
75 | Block | Killed | 89 : 43 | {
... } |
{} |
76 | StringLiteral | Killed | 90 : 24 | `${ ... ` |
"" |
77 | IfStatement | Killed | 93 : 10 | . ... ]) |
|
78 | IfStatement | Killed | 93 : 10 | . ... ]) |
|
79 | BinaryExpression | Killed | 93 : 10 | . ... ]) |
. ... ] |
80 | BinaryExpression | Killed | 93 : 29 | ! ... ] |
! ... ] |
81 | ConditionalExpression | Killed | 93 : 29 | ! ... ] |
|
82 | ConditionalExpression | Killed | 93 : 29 | ! ... ] |
|
83 | PrefixUnaryExpression | Killed | 93 : 29 | ! |
|
84 | PrefixUnaryExpression | Killed | 93 : 40 | ! ... ] |
[ ... ] |
85 | Block | Killed | 93 : 66 | {
... } |
{} |
86 | StringLiteral | Killed | 94 : 24 | `${ ... }` |
"" |
87 | Block | Killed | 104 : 54 | {
... }
} |
{} |
88 | BinaryExpression | Survived | 105 : 20 | ||
... . ) |
&& ... . |
89 | ConditionalExpression | Survived | 105 : 20 | ||
... . ) |
|
90 | ConditionalExpression | Survived | 105 : 20 | ||
... . ) |
|
91 | BinaryExpression | Survived | 106 : 5 | && ... . |
&& ... . |
92 | ConditionalExpression | Survived | 106 : 5 | && ... . |
|
93 | ConditionalExpression | Survived | 106 : 5 | && ... . |
|
94 | BinaryExpression | Killed | 106 : 5 | && ... . |
|| ... . |
95 | ConditionalExpression | Survived | 106 : 5 | && ... . |
|
96 | ConditionalExpression | Survived | 106 : 5 | && ... . |
|
97 | IfStatement | Killed | 108 : 6 | . ... . |
|
98 | IfStatement | Killed | 108 : 6 | . ... . |
|
99 | BinaryExpression | Killed | 108 : 6 | . ... ' |
. ... ' |
100 | BinaryExpression | Killed | 108 : 6 | . ... . |
. ... . |
101 | ConditionalExpression | Killed | 108 : 6 | . ... ' |
|
102 | ConditionalExpression | Killed | 108 : 6 | . ... ' |
|
103 | StringLiteral | Killed | 108 : 39 | ' ' |
"" |
104 | BinaryExpression | Killed | 108 : 53 | . ... . |
. ... . |
105 | ConditionalExpression | Killed | 108 : 53 | . ... . |
|
106 | ConditionalExpression | Killed | 108 : 53 | . ... . |
|
107 | Block | Killed | 108 : 92 | {
...;
} |
{} |
108 | StringLiteral | Killed | 109 : 20 | `${ ... .` |
"" |
109 | IfStatement | Killed | 112 : 6 | . ... ' |
|
110 | IfStatement | Killed | 112 : 6 | . ... ' |
|
111 | BinaryExpression | Killed | 112 : 6 | . ... ' |
. ... ' |
112 | StringLiteral | Killed | 112 : 41 | ' ' |
"" |
113 | Block | Killed | 112 : 51 | {
...;
} |
{} |
114 | StringLiteral | Killed | 113 : 20 | `${ ... .` |
"" |
115 | IfStatement | Killed | 116 : 6 | . ... ' |
|
116 | IfStatement | Killed | 116 : 6 | . ... ' |
|
117 | BinaryExpression | Killed | 116 : 6 | . ... ' |
. ... ' |
118 | StringLiteral | Killed | 116 : 44 | ' ' |
"" |
119 | Block | Killed | 116 : 54 | {
...;
} |
{} |
120 | StringLiteral | Killed | 118 : 6 | `${ ... .` |
"" |
121 | IfStatement | Killed | 123 : 6 | . ... . |
|
122 | IfStatement | Killed | 123 : 6 | . ... . |
|
123 | BinaryExpression | Killed | 123 : 6 | . ... . |
. ... . |
124 | BinaryExpression | Killed | 123 : 6 | . ... ' |
. ... ' |
125 | ConditionalExpression | Killed | 123 : 6 | . ... ' |
|
126 | ConditionalExpression | Survived | 123 : 6 | . ... ' |
|
127 | StringLiteral | Killed | 123 : 51 | ' ' |
"" |
128 | BinaryExpression | Killed | 124 : 4 | . ... . |
. ... . |
129 | ConditionalExpression | Killed | 124 : 4 | . ... . |
|
130 | ConditionalExpression | Killed | 124 : 4 | . ... . |
|
131 | Block | Killed | 124 : 74 | {
...;
} |
{} |
132 | StringLiteral | Killed | 125 : 20 | `${ ... .` |
"" |
133 | IfStatement | Killed | 128 : 6 | . ... ' |
|
134 | IfStatement | Killed | 128 : 6 | . ... ' |
|
135 | BinaryExpression | Killed | 128 : 6 | . ... ' |
. ... ' |
136 | StringLiteral | Killed | 128 : 50 | ' ' |
"" |
137 | Block | Killed | 128 : 60 | {
...;
} |
{} |
138 | StringLiteral | Killed | 130 : 6 | `${ ... .` |
"" |
139 | IfStatement | Killed | 132 : 13 | . ...== '' |
|
140 | IfStatement | Killed | 132 : 13 | . ...== '' |
|
141 | BinaryExpression | Killed | 132 : 13 | . ...== '' |
. ...== '' |
142 | StringLiteral | Killed | 132 : 50 | '' |
" ... !" |
143 | Block | Killed | 132 : 54 | {
...;
} |
{} |
144 | StringLiteral | Killed | 134 : 6 | `${ ... .` |
"" |
145 | IfStatement | Killed | 138 : 6 | ! ... ) |
|
146 | IfStatement | Killed | 138 : 6 | ! ... ) |
|
147 | PrefixUnaryExpression | Killed | 138 : 6 | ! ... ) |
. ... ) |
148 | Block | Killed | 138 : 62 | {
...;
} |
{} |
149 | StringLiteral | Killed | 140 : 6 | `${ ... .` |
"" |
150 | Block | Killed | 149 : 61 | {
... }
} |
{} |
151 | ConditionalExpression | Killed | 150 : 17 | || ... ' |
|
152 | ConditionalExpression | Killed | 150 : 17 | || ... ' |
|
153 | BinaryExpression | Survived | 150 : 17 | || ... ' |
( ... ' |
154 | BinaryExpression | Survived | 150 : 17 | || ... . |
&& ... . |
155 | ConditionalExpression | Survived | 150 : 17 | || ... . |
|
156 | ConditionalExpression | Killed | 150 : 17 | || ... . |
|
157 | StringLiteral | Survived | 150 : 58 | ' ' |
"" |
158 | IfStatement | Killed | 152 : 6 | . ... ' |
|
159 | IfStatement | Killed | 152 : 6 | . ... ' |
|
160 | BinaryExpression | Killed | 152 : 6 | . ... ' |
. ... ' |
161 | StringLiteral | Killed | 152 : 45 | ' ' |
"" |
162 | Block | Killed | 152 : 57 | {
...;
} |
{} |
163 | StringLiteral | Killed | 153 : 20 | `${ ... .` |
"" |
164 | IfStatement | Killed | 156 : 6 | . ... ' |
|
165 | IfStatement | Killed | 156 : 6 | . ... ' |
|
166 | BinaryExpression | Killed | 156 : 6 | . ... ' |
. ... ' |
167 | StringLiteral | Killed | 156 : 39 | ' ' |
"" |
168 | Block | Killed | 156 : 51 | {
...;
} |
{} |
169 | StringLiteral | Killed | 157 : 20 | `${ ... .` |
"" |
170 | IfStatement | Killed | 160 : 6 | . ... ' |
|
171 | IfStatement | Killed | 160 : 6 | . ... ' |
|
172 | BinaryExpression | Killed | 160 : 6 | . ... ' |
. ... ' |
173 | StringLiteral | Killed | 160 : 44 | ' ' |
"" |
174 | Block | Killed | 160 : 56 | {
...;
} |
{} |
175 | StringLiteral | Killed | 161 : 20 | `${ ... .` |
"" |
176 | Block | Killed | 171 : 55 | {
... }
} |
{} |
177 | IfStatement | Killed | 172 : 6 | ! ... -') |
|
178 | IfStatement | Killed | 172 : 6 | ! ... -') |
|
179 | PrefixUnaryExpression | Killed | 172 : 6 | ! ... -') |
. ... -') |
180 | StringLiteral | Killed | 172 : 29 | ' ... -' |
"" |
181 | Block | Killed | 172 : 52 | {
...;
} |
{} |
182 | StringLiteral | Killed | 173 : 20 | ` ... -'` |
"" |
183 | IfStatement | Killed | 176 : 6 | . ... ] |
|
184 | IfStatement | Killed | 176 : 6 | . ... ] |
|
185 | BinaryExpression | Killed | 176 : 6 | . ... ] |
. ... ] |
186 | Block | Killed | 176 : 66 | {
...
} |
{} |
187 | StringLiteral | Killed | 177 : 20 | ` ... ` |
"" |
188 | Block | Killed | 187 : 43 | {
/... ;
} |
{} |
189 | Block | Killed | 191 : 40 | {
...}
} |
{} |
190 | IfStatement | Killed | 193 : 8 | . ... ' |
|
191 | IfStatement | Killed | 193 : 8 | . ... ' |
|
192 | BinaryExpression | Killed | 193 : 8 | . ... ' |
. ... ' |
193 | StringLiteral | Killed | 193 : 50 | ' ' |
"" |
194 | Block | Killed | 193 : 63 | {
... } |
{} |
195 | BooleanSubstitution | Killed | 209 : 51 |
|
|
196 | Block | Killed | 209 : 58 | {
/... ;
} |
{} |
197 | IfStatement | Killed | 211 : 6 | === '... === |
|
198 | IfStatement | Killed | 211 : 6 | === '... === |
|
199 | BinaryExpression | Killed | 211 : 6 | === '... === |
=== '... === |
200 | BinaryExpression | Killed | 211 : 6 | === ' ' |
!== ' ' |
201 | ConditionalExpression | Killed | 211 : 6 | === ' ' |
|
202 | ConditionalExpression | Killed | 211 : 6 | === ' ' |
|
203 | StringLiteral | Killed | 211 : 22 | ' ' |
"" |
204 | BinaryExpression | Killed | 211 : 37 | === |
!== |
205 | ConditionalExpression | Killed | 211 : 37 | === |
|
206 | ConditionalExpression | Killed | 211 : 37 | === |
|
207 | Block | Survived | 211 : 52 | {
...;
} |
{} |
208 | IfStatement | Killed | 213 : 13 | === ' ' |
|
209 | IfStatement | Killed | 213 : 13 | === ' ' |
|
210 | BinaryExpression | Killed | 213 : 13 | === ' ' |
!== ' ' |
211 | StringLiteral | Killed | 213 : 34 | ' ' |
"" |
212 | Block | Killed | 213 : 47 | {
...;
} |
{} |
213 | IfStatement | Killed | 215 : 13 | . ... ) |
|
214 | IfStatement | Killed | 215 : 13 | . ... ) |
|
215 | Block | Killed | 215 : 39 | {
...;
} |
{} |
216 | IfStatement | Killed | 216 : 8 |
|
|
217 | IfStatement | Killed | 216 : 8 |
|
|
218 | IfStatement | Killed | 217 : 8 | ! ... ) |
|
219 | IfStatement | Killed | 217 : 8 | ! ... ) |
|
220 | PrefixUnaryExpression | Killed | 217 : 8 | ! ... ) |
. ( ) |
221 | StringLiteral | Survived | 217 : 50 | ` ... }` |
"" |
222 | Block | Killed | 219 : 30 | {
... } |
{} |
223 | IfStatement | Killed | 220 : 10 | ! ... )) |
|
224 | PrefixUnaryExpression | Killed | 220 : 10 | ! ... )) |
. ... )) |
225 | IfStatement | Survived | 220 : 10 | ! ... )) |
|
226 | IfStatement | Killed | 224 : 13 | === ' ' |
|
227 | IfStatement | Killed | 224 : 13 | === ' ' |
|
228 | BinaryExpression | Killed | 224 : 13 | === ' ' |
!== ' ' |
229 | StringLiteral | Killed | 224 : 34 | ' ' |
"" |
230 | Block | Killed | 224 : 44 | {
...;
} |
{} |
231 | IfStatement | Killed | 225 : 8 | !== ' ' |
|
232 | IfStatement | Survived | 225 : 8 | !== ' ' |
|
233 | BinaryExpression | Killed | 225 : 8 | !== ' ' |
=== ' ' |
234 | StringLiteral | Killed | 225 : 24 | ' ' |
"" |
235 | StringLiteral | Survived | 225 : 54 | ` ... }` |
"" |
236 | IfStatement | Killed | 226 : 8 | . ( ) |
|
237 | IfStatement | Killed | 226 : 8 | . ( ) |
|
238 | StringLiteral | Survived | 226 : 49 | ' ... ' |
"" |
239 | Block | Killed | 227 : 42 | {
... } |
{} |
240 | BinaryExpression | Killed | 228 : 35 | ||
... ') |
&& ... ' |
241 | ConditionalExpression | Killed | 228 : 35 | ||
... ') |
|
242 | ConditionalExpression | Killed | 228 : 35 | ||
... ') |
|
243 | BinaryExpression | Killed | 229 : 9 | === '... ' |
=== '... ' |
244 | ConditionalExpression | Killed | 229 : 9 | === '... ' |
|
245 | ConditionalExpression | Killed | 229 : 9 | === '... ' |
|
246 | ConditionalExpression | Killed | 229 : 9 | === ' ' |
|
247 | BinaryExpression | Killed | 229 : 9 | === ' ' |
!== ' ' |
248 | ConditionalExpression | Killed | 229 : 9 | === ' ' |
|
249 | StringLiteral | Killed | 229 : 17 | ' ' |
"" |
250 | BinaryExpression | Killed | 229 : 31 | [ ]... ' |
[ ]... ' |
251 | ConditionalExpression | Killed | 229 : 31 | [ ]... ' |
|
252 | ConditionalExpression | Survived | 229 : 31 | [ ]... ' |
|
253 | StringLiteral | Killed | 229 : 52 | ' ' |
"" |
254 | Block | Killed | 250 : 43 | {
...});
} |
{} |
255 | Block | Killed | 251 : 27 | {
...;
} |
{} |
256 | IfStatement | Killed | 252 : 8 | === ' ' |
|
257 | IfStatement | Survived | 252 : 8 | === ' ' |
|
258 | BinaryExpression | Killed | 252 : 8 | === ' ' |
!== ' ' |
259 | StringLiteral | Killed | 252 : 24 | ' ' |
"" |
260 | Block | Survived | 252 : 34 | {
... } |
{} |
261 | Block | Killed | 273 : 25 | {
...));
} |
{} |
262 | Block | Killed | 283 : 35 | {
... ;
} |
{} |
263 | IfStatement | Killed | 288 : 6 | . ... ) |
|
264 | IfStatement | Killed | 288 : 6 | . ... ) |
|
265 | BinaryExpression | Killed | 288 : 6 | . ... ) |
. ... ) |
266 | Block | Killed | 288 : 66 | {
...}
} |
{} |
267 | ForStatement | Killed | 289 : 20 | < ... . |
|
268 | BinaryExpression | Killed | 289 : 20 | < ... . |
<= ... . |
269 | BinaryExpression | Killed | 289 : 20 | < ... . |
>= ... . |
270 | PostfixUnaryExpression | Killed | 289 : 46 | ++ |
-- |
271 | Block | Killed | 289 : 51 | {
... } |
{} |
272 | BinaryExpression | Killed | 291 : 50 | . ...|| [] |
. ...&& [] |
273 | ConditionalExpression | Killed | 291 : 50 | . ...|| [] |
|
274 | ConditionalExpression | Killed | 291 : 50 | . ...|| [] |
|
275 | IfStatement | Killed | 295 : 6 | . ... ) |
|
276 | IfStatement | Killed | 295 : 6 | . ... ) |
|
277 | Block | Killed | 295 : 34 | {
...;
} |
{} |
278 | Block | Killed | 310 : 45 | {
/... ;
} |
{} |
279 | Block | Killed | 314 : 28 | {
...;
} |
{} |
280 | BinaryExpression | Killed | 315 : 25 | . ... ) |
. ... ) |
281 | ConditionalExpression | Killed | 315 : 25 | . ... ) |
|
282 | ConditionalExpression | Killed | 315 : 25 | . ... ) |
|
283 | BinaryExpression | Killed | 315 : 68 | . === . |
. !== . |
284 | ConditionalExpression | Killed | 315 : 68 | . === . |
|
285 | ConditionalExpression | Killed | 315 : 68 | . === . |
|
286 | IfStatement | Killed | 316 : 8 | ! |
|
287 | IfStatement | Killed | 316 : 8 | ! |
|
288 | PrefixUnaryExpression | Killed | 316 : 8 | ! |
|
289 | Block | Killed | 316 : 23 | {
... } |
{} |
290 | Block | Killed | 334 : 33 | {
...;
} |
{} |
291 | ObjectLiteral | Killed | 335 : 19 | { :... '} |
{} |
292 | StringLiteral | Survived | 335 : 25 | ' ' |
"" |
293 | StringLiteral | Killed | 335 : 46 | ' : ... ' |
"" |
294 | StringLiteral | Killed | 336 : 21 | ' ' |
"" |
295 | BinaryExpression | Killed | 337 : 21 | && . |
|| . |
296 | ConditionalExpression | Killed | 337 : 21 | && . |
|
297 | ConditionalExpression | Killed | 337 : 21 | && . |
|
298 | IfStatement | Killed | 339 : 8 | ! |
|
299 | PrefixUnaryExpression | Killed | 339 : 8 | ! |
|
300 | IfStatement | Killed | 339 : 8 | ! |
|
301 | Block | Killed | 339 : 21 | {
... } |
{} |
302 | IfStatement | Killed | 344 : 8 | && ! ... ) |
|
303 | IfStatement | Killed | 344 : 8 | && ! ... ) |
|
304 | BinaryExpression | Killed | 344 : 8 | && ! ... ) |
|| ! ... ) |
305 | PrefixUnaryExpression | Killed | 344 : 22 | ! ... ) |
. ... ) |
306 | Block | Killed | 344 : 52 | {
... } |
{} |
307 | StringLiteral | Killed | 345 : 22 | ' ... .' |
"" |
308 | IfStatement | Killed | 352 : 8 | . ... ' |
|
309 | IfStatement | Killed | 352 : 8 | . ... ' |
|
310 | BinaryExpression | Killed | 352 : 8 | . ... ' |
. ... ' |
311 | StringLiteral | Killed | 352 : 31 | ' ... ' |
"" |
312 | Block | Killed | 352 : 50 | {
... } |
{} |
313 | IfStatement | Killed | 356 : 15 | . |
|
314 | IfStatement | Killed | 356 : 15 | . |
|
315 | Block | Killed | 356 : 35 | {
... } |
{} |
316 | BinaryExpression | Killed | 380 : 22 | . || |
. && |
317 | ConditionalExpression | Killed | 380 : 22 | . || |
|
318 | ConditionalExpression | Killed | 380 : 22 | . || |
|
319 | BinaryExpression | Killed | 382 : 18 | . || |
. && |
320 | ConditionalExpression | Killed | 382 : 18 | . || |
|
321 | ConditionalExpression | Killed | 382 : 18 | . || |
|
322 | Block | Killed | 400 : 19 | {
...;
} |
{} |
323 | IfStatement | Killed | 403 : 8 | . |
|
324 | IfStatement | Killed | 403 : 8 | . |
|
325 | Block | Killed | 403 : 27 | {
... } |
{} |
326 | Block | Killed | 404 : 44 | {
... } |
{} |
327 | Block | Killed | 405 : 51 | {
... } |
{} |
328 | IfStatement | Killed | 409 : 14 | . ... === |
|
329 | IfStatement | Killed | 409 : 14 | . ... === |
|
330 | BinaryExpression | Killed | 409 : 14 | . ... === |
. ... !== |
331 | Block | Killed | 409 : 62 | {
... } |
{} |
332 | IfStatement | Killed | 417 : 8 | . |
|
333 | IfStatement | Killed | 417 : 8 | . |
|
334 | Block | Killed | 417 : 27 | {
... } |
{} |
335 | Block | Killed | 418 : 49 | {
... } |
{} |
336 | IfStatement | Killed | 421 : 12 | . ... === |
|
337 | IfStatement | Killed | 421 : 12 | . ... === |
|
338 | BinaryExpression | Killed | 421 : 12 | . ... === |
. ... !== |
339 | Block | Killed | 421 : 57 | {
... } |
{} |
340 | Block | Killed | 439 : 48 | {
...;
} |
{} |
341 | IfStatement | Killed | 440 : 8 | . ... . |
|
342 | IfStatement | Killed | 440 : 8 | . ... . |
|
343 | BinaryExpression | Killed | 440 : 8 | . ... . |
. ... . |
344 | Block | Killed | 440 : 46 | {
... } |
{} |
345 | Block | Killed | 441 : 44 | {
... } |
{} |
346 | ConditionalExpression | Killed | 443 : 25 | . ... . |
|
347 | BinaryExpression | Killed | 443 : 25 | . ... . |
. ... . |
348 | ConditionalExpression | Killed | 443 : 25 | . ... . |
|
349 | BinaryExpression | Killed | 444 : 59 | . === |
. !== |
350 | ConditionalExpression | Killed | 444 : 59 | . === |
|
351 | ConditionalExpression | Killed | 444 : 59 | . === |
|
352 | IfStatement | Killed | 446 : 12 | ! |
|
353 | IfStatement | Killed | 446 : 12 | ! |
|
354 | PrefixUnaryExpression | Killed | 446 : 12 | ! |
|
355 | Block | Killed | 446 : 23 | {
... } |
{} |
356 | Block | Killed | 448 : 15 | {
... } |
{} |
357 | Block | Killed | 465 : 52 | {
...;
} |
{} |
358 | BinaryExpression | Killed | 466 : 26 | . || [] |
. && [] |
359 | ConditionalExpression | Killed | 466 : 26 | . || [] |
|
360 | ConditionalExpression | Killed | 466 : 26 | . || [] |
|
361 | BinaryExpression | Killed | 467 : 24 | ( ...|| [] |
&& ...&& [] |
362 | ConditionalExpression | Killed | 467 : 24 | ( ...|| [] |
|
363 | ConditionalExpression | Killed | 467 : 24 | ( ...|| [] |
|
364 | BinaryExpression | Killed | 467 : 25 | && . |
|| . |
365 | ConditionalExpression | Killed | 467 : 25 | && . |
|
366 | ConditionalExpression | Killed | 467 : 25 | && . |
|
367 | ArrayLiteral | Killed | 468 : 32 | [... ... ] |
[] |
368 | Block | Killed | 470 : 42 | {
... } |
{} |
369 | StringLiteral | Killed | 473 : 69 | ' ' |
"" |
370 | Block | Killed | 487 : 43 | {
...;
} |
{} |
371 | IfStatement | Killed | 488 : 8 | ! |
|
372 | IfStatement | Killed | 488 : 8 | ! |
|
373 | PrefixUnaryExpression | Killed | 488 : 8 | ! |
|
374 | Block | Killed | 488 : 17 | {
... } |
{} |
375 | Block | Killed | 501 : 48 | {
...;
} |
{} |
376 | ConditionalExpression | Killed | 505 : 37 | ( ... . |
|
377 | BinaryExpression | Killed | 505 : 37 | ( ... . |
&& ... . |
378 | ConditionalExpression | Killed | 505 : 37 | ( ... . |
|
379 | BinaryExpression | Killed | 505 : 38 | && . |
|| . |
380 | ConditionalExpression | Killed | 505 : 38 | && . |
|
381 | ConditionalExpression | Killed | 505 : 38 | && . |
|
382 | BooleanSubstitution | Killed | 509 : 80 |
|
|
383 | BinaryExpression | Killed | 512 : 36 | || {} |
&& {} |
384 | ConditionalExpression | Killed | 512 : 36 | || {} |
|
385 | ConditionalExpression | Killed | 512 : 36 | || {} |
|
386 | BooleanSubstitution | Killed | 512 : 93 |
|
|
387 | Block | Killed | 525 : 38 | {
...;
} |
{} |
388 | IfStatement | Killed | 526 : 8 | ! |
|
389 | IfStatement | Killed | 526 : 8 | ! |
|
390 | PrefixUnaryExpression | Killed | 526 : 8 | ! |
|
391 | Block | Killed | 526 : 17 | {
... } |
{} |
392 | Block | Killed | 530 : 42 | {
... } |
{} |
393 | IfStatement | Killed | 531 : 10 | === ' ' |
|
394 | IfStatement | Killed | 531 : 10 | === ' ' |
|
395 | BinaryExpression | Killed | 531 : 10 | === ' ' |
!== ' ' |
396 | StringLiteral | Killed | 531 : 27 | ' ' |
"" |
397 | Block | Killed | 531 : 37 | {
... } |
{} |
398 | ObjectLiteral | Killed | 533 : 15 | { ...: {}} |
{} |
399 | IfStatement | Killed | 534 : 17 | ' ... ' |
|
400 | IfStatement | Killed | 534 : 17 | ' ... ' |
|
401 | BinaryExpression | Killed | 534 : 17 | ' ... ' |
' ... ' |
402 | StringLiteral | Killed | 534 : 17 | ' ... ' |
"" |
403 | ConditionalExpression | Killed | 534 : 46 | . ... ' |
|
404 | BinaryExpression | Killed | 534 : 46 | . ... ' |
. ... ' |
405 | ConditionalExpression | Survived | 534 : 46 | . ... ' |
|
406 | StringLiteral | Killed | 534 : 84 | ' ' |
"" |
407 | Block | Killed | 534 : 96 | {
... } |
{} |
408 | IfStatement | Killed | 537 : 17 | ' ... ' |
|
409 | IfStatement | Killed | 537 : 17 | ' ... ' |
|
410 | BinaryExpression | Killed | 537 : 17 | ' ... ' |
' ... ' |
411 | StringLiteral | Killed | 537 : 17 | ' ' |
"" |
412 | ConditionalExpression | Killed | 537 : 36 | . ... ' |
|
413 | BinaryExpression | Killed | 537 : 36 | . ... ' |
. ... ' |
414 | ConditionalExpression | Survived | 537 : 36 | . ... ' |
|
415 | StringLiteral | Killed | 537 : 58 | ' ' |
"" |
416 | Block | Killed | 537 : 68 | {
... } |
{} |
417 | IfStatement | Killed | 540 : 17 | ' ... ' |
|
418 | IfStatement | Killed | 540 : 17 | ' ... ' |
|
419 | BinaryExpression | Killed | 540 : 17 | ' ... ' |
' ... ' |
420 | StringLiteral | Killed | 540 : 17 | ' ' |
"" |
421 | BinaryExpression | Killed | 540 : 37 | . ... ' |
. ... ' |
422 | ConditionalExpression | Killed | 540 : 37 | . ... ' |
|
423 | ConditionalExpression | Survived | 540 : 37 | . ... ' |
|
424 | StringLiteral | Killed | 540 : 60 | ' ' |
"" |
425 | Block | Killed | 540 : 72 | {
... } |
{} |
426 | ObjectLiteral | Killed | 542 : 15 | { ...: {}} |
{} |
427 | Block | Killed | 543 : 13 | {
... } |
{} |
428 | BinaryExpression | Killed | 544 : 24 | ' ... ) |
' ... ) |
429 | StringLiteral | Killed | 544 : 24 | ' ... ' |
"" |
430 | Block | Killed | 562 : 44 | {
...;
} |
{} |
431 | Block | Killed | 563 : 47 | {
... } |
{} |
432 | IfStatement | Killed | 564 : 10 | === ' ' |
|
433 | IfStatement | Killed | 564 : 10 | === ' ' |
|
434 | BinaryExpression | Killed | 564 : 10 | === ' ' |
!== ' ' |
435 | StringLiteral | Killed | 564 : 30 | ' ' |
"" |
436 | Block | Killed | 564 : 40 | {
... } |
{} |
437 | ObjectLiteral | Killed | 566 : 15 | { ...: {}} |
{} |
438 | IfStatement | Killed | 567 : 17 | ' ... ' |
|
439 | IfStatement | Killed | 567 : 17 | ' ... ' |
|
440 | BinaryExpression | Killed | 567 : 17 | ' ... ' |
' ... ' |
441 | StringLiteral | Killed | 567 : 17 | ' ... ' |
"" |
442 | StringLiteral | Killed | 567 : 49 | ' ' |
"" |
443 | Block | Killed | 567 : 73 | {
... } |
{} |
444 | IfStatement | Killed | 570 : 17 | ' ' |
|
445 | IfStatement | Killed | 570 : 17 | ' ' |
|
446 | StringLiteral | Killed | 570 : 17 | ' ' |
"" |
447 | Block | Killed | 570 : 37 | {
... } |
{} |
448 | IfStatement | Killed | 572 : 12 | . ... ' |
|
449 | IfStatement | Killed | 572 : 12 | . ... ' |
|
450 | BinaryExpression | Killed | 572 : 12 | . ... ' |
. ... ' |
451 | StringLiteral | Killed | 572 : 37 | ' ' |
"" |
452 | Block | Killed | 572 : 47 | {
... } |
{} |
453 | BinaryExpression | Killed | 573 : 26 | ' ... ) |
' ... ) |
454 | StringLiteral | Killed | 573 : 26 | ' ... ' |
"" |
455 | IfStatement | Killed | 576 : 17 | === ' ' |
|
456 | IfStatement | Killed | 576 : 17 | === ' ' |
|
457 | BinaryExpression | Killed | 576 : 17 | === ' ' |
!== ' ' |
458 | StringLiteral | Killed | 576 : 37 | ' ' |
"" |
459 | Block | Killed | 576 : 49 | {
... } |
{} |
460 | ObjectLiteral | Killed | 578 : 15 | { ...: {}} |
{} |
461 | IfStatement | Killed | 579 : 17 | && ... ' |
|
462 | BinaryExpression | Killed | 579 : 17 | && ... ' |
|| ... ' |
463 | IfStatement | Killed | 579 : 17 | && ... ' |
|
464 | ConditionalExpression | Killed | 579 : 29 | . ... ' |
|
465 | BinaryExpression | Killed | 579 : 29 | . ... ' |
. ... ' |
466 | ConditionalExpression | Killed | 579 : 29 | . ... ' |
|
467 | StringLiteral | Killed | 579 : 60 | ' ' |
"" |
468 | Block | Killed | 579 : 72 | {
... } |
{} |
469 | ObjectLiteral | Killed | 581 : 15 | { ...: {}} |
{} |
470 | Block | Killed | 582 : 13 | {
... } |
{} |
471 | BinaryExpression | Killed | 583 : 24 | ' ... ) |
' ... ) |
472 | StringLiteral | Killed | 583 : 24 | ' ... ' |
"" |
473 | Block | Killed | 596 : 58 | {
...;
} |
{} |
474 | IfStatement | Killed | 597 : 8 | ! ... ') |
|
475 | IfStatement | Killed | 597 : 8 | ! ... ') |
|
476 | BinaryExpression | Killed | 597 : 8 | ! ... ') |
! ... ' |
477 | PrefixUnaryExpression | Killed | 597 : 8 | ! |
|
478 | BinaryExpression | Killed | 598 : 9 | . ... ' |
. ... ' |
479 | ConditionalExpression | Killed | 598 : 9 | . ... ' |
|
480 | BinaryExpression | Killed | 598 : 9 | . ... ' |
. ... ' |
481 | ConditionalExpression | Survived | 598 : 9 | . ... ' |
|
482 | ConditionalExpression | Killed | 598 : 9 | . ... ' |
|
483 | ConditionalExpression | Survived | 598 : 9 | . ... ' |
|
484 | StringLiteral | Killed | 598 : 39 | ' ' |
"" |
485 | BinaryExpression | Survived | 598 : 53 | . ... ' |
. ... ' |
486 | ConditionalExpression | Survived | 598 : 53 | . ... ' |
|
487 | ConditionalExpression | Survived | 598 : 53 | . ... ' |
|
488 | StringLiteral | Killed | 598 : 83 | ' ' |
"" |
489 | Block | Killed | 598 : 96 | {
... } |
{} |
490 | BinaryExpression | Killed | 602 : 44 | . ... ' |
. ... ' |
491 | ConditionalExpression | Killed | 602 : 44 | . ... ' |
|
492 | ConditionalExpression | Survived | 602 : 44 | . ... ' |
|
493 | StringLiteral | Killed | 602 : 62 | ' ' |
"" |
494 | IfStatement | Killed | 603 : 8 | ! |
|
495 | IfStatement | Killed | 603 : 8 | ! |
|
496 | PrefixUnaryExpression | Killed | 603 : 8 | ! |
|
497 | Block | Killed | 617 : 38 | {
...;
} |
{} |
498 | IfStatement | Killed | 619 : 8 | ! ... . |
|
499 | IfStatement | Killed | 619 : 8 | ! ... . |
|
500 | BinaryExpression | Killed | 619 : 8 | ! ... . |
! ... . |
501 | BinaryExpression | Killed | 619 : 8 | ! ... . |
! ... . |
502 | ConditionalExpression | Killed | 619 : 8 | ! ... . |
|
503 | ConditionalExpression | Killed | 619 : 8 | ! ... . |
|
504 | PrefixUnaryExpression | Killed | 619 : 8 | ! . |
. |
505 | PrefixUnaryExpression | Killed | 619 : 36 | ! . |
. |
506 | PrefixUnaryExpression | Killed | 619 : 60 | ! . |
. |
507 | Block | Killed | 619 : 82 | {
... } |
{} |
508 | BinaryExpression | Killed | 628 : 19 | . .... )) |
. .... )) |
509 | ConditionalExpression | Killed | 628 : 19 | . .... )) |
|
510 | ConditionalExpression | Killed | 628 : 19 | . .... )) |
|
511 | Block | Killed | 648 : 60 | {
...;
} |
{} |
512 | IfStatement | Killed | 649 : 8 | ! |
|
513 | IfStatement | Killed | 649 : 8 | ! |
|
514 | PrefixUnaryExpression | Killed | 649 : 8 | ! |
|
515 | Block | Killed | 649 : 24 | {
... } |
{} |
516 | ObjectLiteral | Killed | 650 : 13 | { ... ()} |
{} |
517 | IfStatement | Killed | 653 : 8 | . ... . |
|
518 | IfStatement | Killed | 653 : 8 | . ... . |
|
519 | BinaryExpression | Killed | 653 : 8 | . ... . |
. ... . |
520 | Block | Killed | 653 : 52 | {
... } |
{} |
521 | StringLiteral | Survived | 654 : 22 | ' ... ' |
"" |
522 | PrefixUnaryExpression | Killed | 659 : 37 | !! . |
! . |
523 | PrefixUnaryExpression | Killed | 659 : 38 | ! . |
. |
524 | PrefixUnaryExpression | Killed | 660 : 34 | !! . |
! . |
525 | PrefixUnaryExpression | Killed | 660 : 35 | ! . |
. |
526 | BinaryExpression | Killed | 661 : 24 | . ...|| [] |
. ...&& [] |
527 | ConditionalExpression | Killed | 661 : 24 | . ...|| [] |
|
528 | ConditionalExpression | Killed | 661 : 24 | . ...|| [] |
|
529 | BinaryExpression | Killed | 662 : 21 | . ...|| [] |
. ...&& [] |
530 | ConditionalExpression | Killed | 662 : 21 | . ...|| [] |
|
531 | ConditionalExpression | Killed | 662 : 21 | . ...|| [] |
|
532 | BinaryExpression | Killed | 663 : 25 | . ...|| [] |
. ...&& [] |
533 | ConditionalExpression | Killed | 663 : 25 | . ...|| [] |
|
534 | ConditionalExpression | Killed | 663 : 25 | . ...|| [] |
|
535 | Block | Killed | 666 : 38 | {
... } |
{} |
536 | IfStatement | Killed | 667 : 10 | ! ... ] |
|
537 | IfStatement | Killed | 667 : 10 | ! ... ] |
|
538 | PrefixUnaryExpression | Killed | 667 : 10 | ! ... ] |
[ ] |
539 | Block | Killed | 667 : 38 | {
... } |
{} |
540 | StringLiteral | Survived | 668 : 17 | ' ' |
"" |
541 | StringLiteral | Survived | 668 : 27 | ` ... }` |
"" |
542 | Block | Killed | 674 : 44 | {
... } |
{} |
543 | Block | Killed | 675 : 74 | {
... } |
{} |
544 | PrefixUnaryExpression | Killed | 677 : 15 | !! ... ) |
! ... ) |
545 | PrefixUnaryExpression | Killed | 677 : 16 | ! ... ) |
. ... ) |
546 | BinaryExpression | Survived | 677 : 45 | . === |
. !== |
547 | ConditionalExpression | Survived | 677 : 45 | . === |
|
548 | ConditionalExpression | Survived | 677 : 45 | . === |
|
549 | IfStatement | Killed | 680 : 10 | ! |
|
550 | IfStatement | Killed | 680 : 10 | ! |
|
551 | PrefixUnaryExpression | Killed | 680 : 10 | ! |
|
552 | Block | Killed | 680 : 26 | {
... } |
{} |
553 | StringLiteral | Survived | 681 : 63 | ' ' |
"" |
554 | StringLiteral | Survived | 681 : 78 | ' ' |
"" |
555 | StringLiteral | Survived | 682 : 17 | ' ' |
"" |
556 | StringLiteral | Survived | 682 : 27 | ` ... }` |
"" |
557 | IfStatement | Killed | 683 : 17 | . ... ) |
|
558 | IfStatement | Survived | 683 : 17 | . ... ) |
|
559 | BinaryExpression | Survived | 683 : 17 | . ... ) |
. ... ) |
560 | Block | Killed | 683 : 84 | {
... } |
{} |
561 | StringLiteral | Survived | 684 : 17 | ' ' |
"" |
562 | BinaryExpression | Killed | 684 : 27 | `${ ... '` |
`${ ... '` |
563 | StringLiteral | Survived | 684 : 27 | `${ ... ` |
"" |
564 | StringLiteral | Survived | 685 : 12 | `${ ... '` |
"" |
565 | Block | Killed | 692 : 53 | {
... } |
{} |
566 | IfStatement | Killed | 695 : 10 | && |
|
567 | IfStatement | Killed | 695 : 10 | && |
|
568 | BinaryExpression | Survived | 695 : 10 | && |
|| |
569 | Block | Killed | 695 : 61 | {
... } |
{} |
570 | IfStatement | Killed | 697 : 12 | ! ... ) |
|
571 | IfStatement | Killed | 697 : 12 | ! ... ) |
|
572 | PrefixUnaryExpression | Killed | 697 : 12 | ! ... ) |
. ... ) |
573 | Block | Killed | 697 : 47 | {
... } |
{} |
574 | IfStatement | Killed | 700 : 17 |
|
|
575 | IfStatement | Killed | 700 : 17 |
|
|
576 | Block | Killed | 700 : 43 | {
... } |
{} |
577 | IfStatement | Killed | 702 : 12 | ! ... ) |
|
578 | IfStatement | Killed | 702 : 12 | ! ... ) |
|
579 | PrefixUnaryExpression | Killed | 702 : 12 | ! ... ) |
. ... ) |
580 | Block | Killed | 702 : 47 | {
... } |
{} |
581 | IfStatement | Killed | 705 : 17 |
|
|
582 | IfStatement | Killed | 705 : 17 |
|
|
583 | Block | Killed | 705 : 40 | {
... } |
{} |
584 | PrefixUnaryExpression | Killed | 710 : 62 | ! ... . ) |
. ... . ) |
585 | IfStatement | Killed | 712 : 10 | . . |
|
586 | IfStatement | Killed | 712 : 10 | . . |
|
587 | Block | Killed | 712 : 37 | {
... } |
{} |
588 | ObjectLiteral | Killed | 718 : 11 | { ... } |
{} |
589 | Block | Killed | 725 : 31 | {
...;
} |
{} |
590 | IfStatement | Killed | 727 : 8 | ! |
|
591 | IfStatement | Killed | 727 : 8 | ! |
|
592 | PrefixUnaryExpression | Killed | 727 : 8 | ! |
|
593 | Block | Killed | 727 : 21 | {
... } |
{} |
594 | Block | Killed | 731 : 45 | {
... } |
{} |
595 | ObjectLiteral | Killed | 733 : 13 | { , } |
{} |
596 | Block | Killed | 742 : 44 | {
...;
} |
{} |
597 | IfStatement | Killed | 745 : 8 | ! |
|
598 | IfStatement | Killed | 745 : 8 | ! |
|
599 | PrefixUnaryExpression | Killed | 745 : 8 | ! |
|
600 | Block | Killed | 745 : 17 | {
... } |
{} |
601 | Block | Killed | 749 : 46 | {
... } |
{} |
602 | Block | Killed | 761 : 68 | {
...;
} |
{} |
603 | IfStatement | Killed | 762 : 8 | ! |
|
604 | IfStatement | Killed | 762 : 8 | ! |
|
605 | PrefixUnaryExpression | Killed | 762 : 8 | ! |
|
606 | Block | Killed | 762 : 17 | {
... } |
{} |
607 | StringLiteral | Killed | 766 : 50 | ' ' |
"" |
608 | Block | Killed | 767 : 46 | {
... } |
{} |
609 | Block | Killed | 769 : 61 | {
... } |
{} |
610 | IfStatement | Killed | 775 : 10 | . ... && ! |
|
611 | IfStatement | Killed | 775 : 10 | . ... && ! |
|
612 | BinaryExpression | Killed | 775 : 10 | . ... && ! |
. ... || ! |
613 | PrefixUnaryExpression | Killed | 775 : 30 | ! |
|
614 | Block | Killed | 775 : 48 | {
... } |
{} |
615 | BinaryExpression | Survived | 776 : 25 | . ... ' |
. ... ' |
616 | ConditionalExpression | Survived | 776 : 25 | . ... ' |
|
617 | ConditionalExpression | Survived | 776 : 25 | . ... ' |
|
618 | StringLiteral | Survived | 776 : 42 | ' ' |
"" |
619 | StringLiteral | Survived | 777 : 17 | ' ' |
"" |
620 | StringLiteral | Survived | 777 : 27 | ` ... }` |
"" |
621 | BooleanSubstitution | Killed | 778 : 27 |
|
|
622 | Block | Killed | 782 : 22 | {
... } |
{} |
623 | IfStatement | Killed | 784 : 10 | . |
|
624 | IfStatement | Survived | 784 : 10 | . |
|
625 | BooleanSubstitution | Killed | 784 : 35 |
|
|
626 | IfStatement | Killed | 786 : 10 | . ... ' |
|
627 | IfStatement | Killed | 786 : 10 | . ... ' |
|
628 | BinaryExpression | Killed | 786 : 10 | . ... ' |
. ... ' |
629 | StringLiteral | Killed | 786 : 28 | ' ' |
"" |
630 | BooleanSubstitution | Killed | 786 : 50 |
|
|
631 | BinaryExpression | Killed | 787 : 13 | . ... > |
. ... >= |
632 | BinaryExpression | Killed | 787 : 13 | . ... > |
. ... <= |
633 | ConditionalExpression | Killed | 787 : 13 | . ... > |
|
634 | ConditionalExpression | Killed | 787 : 13 | . ... > |
|
635 | Block | Killed | 800 : 42 | {
...;
} |
{} |
636 | ObjectLiteral | Killed | 801 : 19 | { :... '} |
{} |
637 | StringLiteral | Survived | 801 : 25 | ' ... ' |
"" |
638 | StringLiteral | Killed | 801 : 49 | ' : ... ' |
"" |
639 | StringLiteral | Killed | 802 : 21 | ' ' |
"" |
640 | IfStatement | Killed | 804 : 8 | ! |
|
641 | IfStatement | Killed | 804 : 8 | ! |
|
642 | PrefixUnaryExpression | Killed | 804 : 8 | ! |
|
643 | Block | Killed | 804 : 25 | {
... } |
{} |
644 | Block | Killed | 809 : 51 | {
... } |
{} |
645 | IfStatement | Killed | 811 : 10 | ' ... ' |
|
646 | IfStatement | Killed | 811 : 10 | ' ... ' |
|
647 | StringLiteral | Killed | 811 : 10 | ' ... ' |
"" |
648 | Block | Killed | 811 : 37 | {
... } |
{} |
649 | Block | Killed | 813 : 13 | {
... } |
{} |
650 | StringLiteral | Killed | 815 : 28 | `${ ...}. ` |
"" |
651 | BinaryExpression | Killed | 816 : 45 | === |
!== |
652 | ConditionalExpression | Killed | 816 : 45 | === |
|
653 | ConditionalExpression | Killed | 816 : 45 | === |
|
654 | StringLiteral | Killed | 817 : 26 | `../ ... }` |
"" |
655 | IfStatement | Killed | 818 : 12 | ! |
|
656 | PrefixUnaryExpression | Killed | 818 : 12 | ! |
|
657 | IfStatement | Killed | 818 : 12 | ! |
|
658 | Block | Killed | 818 : 24 | {
... } |
{} |
659 | StringLiteral | Killed | 820 : 68 | ' ' |
"" |
660 | ObjectLiteral | Killed | 825 : 13 | {
... } |
{} |
661 | BinaryExpression | Killed | 828 : 17 | . || {} |
. && {} |
662 | ConditionalExpression | Killed | 828 : 17 | . || {} |
|
663 | ConditionalExpression | Killed | 828 : 17 | . || {} |
|
664 | Block | Killed | 845 : 74 | {
...;
} |
{} |
665 | BinaryExpression | Killed | 846 : 49 | === `...}. ` |
!== `...}. ` |
666 | ConditionalExpression | Killed | 846 : 49 | === `...}. ` |
|
667 | ConditionalExpression | Killed | 846 : 49 | === `...}. ` |
|
668 | StringLiteral | Killed | 846 : 55 | `${ }. ` |
"" |
669 | StringLiteral | Killed | 848 : 22 | `../ ... }` |
"" |
670 | IfStatement | Killed | 849 : 8 | ! |
|
671 | IfStatement | Killed | 849 : 8 | ! |
|
672 | PrefixUnaryExpression | Killed | 849 : 8 | ! |
|
673 | Block | Killed | 849 : 23 | {
... } |
{} |
674 | StringLiteral | Killed | 851 : 58 | ' ' |
"" |
675 | ObjectLiteral | Killed | 856 : 11 | {
... } |
{} |
676 | BinaryExpression | Killed | 860 : 15 | || {} |
&& {} |
677 | ConditionalExpression | Killed | 860 : 15 | || {} |
|
678 | ConditionalExpression | Killed | 860 : 15 | || {} |
|
679 | Block | Killed | 872 : 45 | {
...;
} |
{} |
680 | IfStatement | Killed | 873 : 8 | ! |
|
681 | IfStatement | Killed | 873 : 8 | ! |
|
682 | PrefixUnaryExpression | Killed | 873 : 8 | ! |
|
683 | Block | Killed | 873 : 17 | {
... } |
{} |
684 | ObjectLiteral | Killed | 876 : 19 | { :... '} |
{} |
685 | StringLiteral | Survived | 876 : 25 | ' ... ' |
"" |
686 | StringLiteral | Killed | 876 : 52 | ' : ... ' |
"" |
687 | StringLiteral | Killed | 877 : 21 | ' ' |
"" |
688 | Block | Killed | 880 : 42 | {
... } |
{} |
689 | Block | Killed | 881 : 95 | {
... } |
{} |
690 | IfStatement | Killed | 882 : 12 | . |
|
691 | IfStatement | Killed | 882 : 12 | . |
|
692 | Block | Killed | 882 : 35 | {
... } |
{} |
693 | ObjectLiteral | Killed | 883 : 17 | {
... } |
{} |
694 | BinaryExpression | Killed | 887 : 21 | . || {} |
. && {} |
695 | ConditionalExpression | Killed | 887 : 21 | . || {} |
|
696 | ConditionalExpression | Killed | 887 : 21 | . || {} |
|
697 | IfStatement | Killed | 889 : 19 | . |
|
698 | IfStatement | Killed | 889 : 19 | . |
|
699 | Block | Killed | 889 : 48 | {
... } |
{} |
700 | ObjectLiteral | Killed | 891 : 17 | {
... } |
{} |
701 | BinaryExpression | Killed | 895 : 21 | . || {} |
. && {} |
702 | ConditionalExpression | Survived | 895 : 21 | . || {} |
|
703 | ConditionalExpression | Survived | 895 : 21 | . || {} |
|
704 | IfStatement | Killed | 897 : 19 | . |
|
705 | IfStatement | Killed | 897 : 19 | . |
|
706 | Block | Killed | 897 : 38 | {
... } |
{} |
707 | Block | Killed | 901 : 15 | {
... } |
{} |
708 | BinaryExpression | Killed | 902 : 26 | ' ... ) |
' ... ) |
709 | StringLiteral | Survived | 902 : 26 | ' ... : ' |
"" |
710 | ObjectLiteral | Killed | 909 : 33 | { ... } |
{} |
711 | Block | Killed | 925 : 62 | {
...;
} |
{} |
712 | Block | Killed | 930 : 8 | {
... } |
{} |
713 | Block | Killed | 938 : 8 | {
... } |
{} |
714 | BinaryExpression | Killed | 942 : 24 | ' ... }'` |
' ... }'` |
715 | BinaryExpression | Killed | 942 : 24 | ' ...: '') |
' ...: '') |
716 | StringLiteral | Killed | 942 : 24 | ' ... ' |
"" |
717 | StringLiteral | Killed | 943 : 20 | `${ }: ` |
"" |
718 | StringLiteral | Survived | 943 : 38 | '' |
" ... !" |
719 | StringLiteral | Killed | 944 : 8 | `${ ... }'` |
"" |
720 | IfStatement | Killed | 946 : 8 | ! |
|
721 | IfStatement | Killed | 946 : 8 | ! |
|
722 | PrefixUnaryExpression | Killed | 946 : 8 | ! |
|
723 | Block | Killed | 946 : 20 | {
... } |
{} |
724 | BinaryExpression | Killed | 947 : 22 | + ')' |
- ')' |
725 | StringLiteral | Survived | 947 : 36 | ')' |
"" |
726 | Block | Killed | 954 : 8 | {
... } |
{} |
727 | BinaryExpression | Killed | 958 : 20 | + ` ... }')` |
- ` ... }')` |
728 | StringLiteral | Survived | 958 : 34 | ` ... }')` |
"" |