Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lighthouse

Package Overview
Dependencies
Maintainers
4
Versions
1619
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lighthouse - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

lighthouse-core/index.js

21

lighthouse-cli/index.js

@@ -22,3 +22,2 @@ #!/usr/bin/env node

const yargs = require('yargs');
const log = require('../lighthouse-core/lib/log.js');
const semver = require('semver');

@@ -40,3 +39,2 @@ const Printer = require('./printer');

.usage('$0 url')
.demand(1, 'Please provide a url')

@@ -104,2 +102,11 @@ // List of options

.default('output-path', 'stdout')
.check(argv => {
// Make sure lighthouse has been passed a url, or at least one of --list-all-audits
// or --list-trace-categories. If not, stop the program and ask for a url
if (!argv.listAllAudits && !argv.listTraceCategories && argv._.length === 0) {
throw new Error('Please provide a url');
}
return true;
})
.argv;

@@ -119,5 +126,5 @@

if (cli.listTraceCategories) {
const categories = lighthouse.traceCategories;
const traceCategories = lighthouse.traceCategories;
process.stdout.write(JSON.stringify({traceCategories: categories}));
process.stdout.write(JSON.stringify({traceCategories}));
process.exit(0);

@@ -132,8 +139,2 @@ }

// If the URL isn't https or localhost complain to the user.
if (url.indexOf('https') !== 0 && url.indexOf('http://localhost') !== 0) {
log.warn('Lighthouse', 'The URL provided should be on HTTPS');
log.warn('Lighthouse', 'Performance stats will be skewed redirecting from HTTP to HTTPS.');
}
// set logging preferences

@@ -140,0 +141,0 @@ flags.logLevel = 'info';

@@ -47,3 +47,3 @@ /**

if (!OUTPUT_MODE.hasOwnProperty(mode)) {
log.log('warn', `Unknown output mode ${mode}; using pretty`);
log.warn('Printer', `Unknown output mode ${mode}; using pretty`);
return OUTPUT_MODE.pretty;

@@ -61,3 +61,3 @@ }

if (!path) {
log.log('warn', 'No output path set; using stdout');
log.warn('Printer', 'No output path set; using stdout');
return 'stdout';

@@ -153,3 +153,3 @@ }

}
log.info('printer', `${outputMode} output written to ${filePath}`);
log.log('Printer', `${outputMode} output written to ${filePath}`);
resolve();

@@ -156,0 +156,0 @@ });

@@ -24,5 +24,9 @@ /**

describe('CLI Tests', function() {
it('should list all audits and exit immediately after', () => {
it('fails if a url is not provided', () => {
assert.throws(() => childProcess.execSync('node lighthouse-cli/index.js'));
});
it('should list all audits without a url and exit immediately after', () => {
const output = JSON.parse(childProcess.execSync(
'node lighthouse-cli/index.js https://example.com --list-all-audits').toString());
'node lighthouse-cli/index.js --list-all-audits').toString());
assert(Array.isArray(output.audits));

@@ -32,5 +36,5 @@ assert(output.audits.length > 0);

it('should print trace categories list-trace-categories flag and exit immediately after', () => {
it('accepts just the list-trace-categories flag and exit immediately after', () => {
const output = JSON.parse(childProcess.execSync(
'node lighthouse-cli/index.js https://example.com --list-trace-categories').toString());
'node lighthouse-cli/index.js --list-trace-categories').toString());
assert(Array.isArray(output.traceCategories));

@@ -37,0 +41,0 @@ assert(output.traceCategories.length > 0);

@@ -40,3 +40,4 @@ /**

return HTTPS.generateAuditResult({
value: !!artifacts.HTTPS
value: artifacts.HTTPS.value,
debugString: artifacts.HTTPS.debugString
});

@@ -43,0 +44,0 @@ }

@@ -21,2 +21,17 @@ /**

/**
* The relationship between these root modules:
*
* core.js - the gathering, auditing and aggregation
* runner.js - the shared handler (for both module & extension) that needs to be given a driver,
* and sets up the core to do its job
* index.js - the require('lighthouse') hook for Node modules (including the CLI)
*
* lighthouse-cli \
* -- index.js \
* ----- runner.js ----> core.js [Gather / Audit / Aggregate]
* lighthouse-extension /
*
*/
class Core {

@@ -75,4 +90,4 @@ static audit(artifacts, audits) {

if (rejected.length) {
log.log('info', 'Running these audits:', `${filteredAudits.join(', ')}`);
log.log('info', 'Skipping these audits:', `${rejected.join(', ')}`);
log.log('Running these audits:', `${filteredAudits.join(', ')}`);
log.log('Skipping these audits:', `${rejected.join(', ')}`);
}

@@ -79,0 +94,0 @@

@@ -87,3 +87,3 @@ /**

// log events received
this._chrome.on('event', req => _log('verbose', '<=', req));
this._chrome.on('event', req => _log('<=', req, 'verbose'));
}

@@ -101,3 +101,3 @@

// log event listeners being bound
_log('info', 'listen for event =>', {method: eventName});
_log('listen for event =>', {method: eventName});
this._chrome.on(eventName, cb);

@@ -117,3 +117,3 @@ }

// log event listeners being bound
_log('info', 'listen once for event =>', {method: eventName});
_log('listen once for event =>', {method: eventName});
this._chrome.once(eventName, cb);

@@ -147,10 +147,10 @@ }

return new Promise((resolve, reject) => {
_log('http', 'method => browser', {method: command, params: params});
_log('method => browser', {method: command, params: params});
this._chrome.send(command, params, (err, result) => {
if (err) {
_log('error', 'method <= browser', {method: command, params: result});
_log('method <= browser ERR', {method: command, params: result}, 'error');
return reject(result);
}
_log('http', 'method <= browser OK', {method: command, params: result});
_log('method <= browser OK', {method: command, params: result});
resolve(result);

@@ -162,9 +162,9 @@ });

function _log(level, prefix, data) {
function _log(prefix, data, level) {
const columns = (typeof process === 'undefined') ? Infinity : process.stdout.columns;
const maxLength = columns - data.method.length - prefix.length - 7;
const maxLength = columns - data.method.length - prefix.length - 18;
const snippet = data.params ? JSON.stringify(data.params).substr(0, maxLength) : '';
log.log(level, prefix, data.method, snippet);
log[level ? level : 'log'](prefix, data.method, snippet);
}
module.exports = CriDriver;

@@ -126,7 +126,7 @@ /**

if (!this._tabId) {
log.log('error', 'No tabId set for sendCommand');
log.error('No tabId set for sendCommand');
}
chrome.debugger.sendCommand({tabId: this._tabId}, command, params, result => {
if (chrome.runtime.lastError) {
log.log('error', 'method <= browser', command, result);
log.error('method <= browser', command, result);
return reject(chrome.runtime.lastError);

@@ -133,0 +133,0 @@ }

@@ -39,2 +39,9 @@ /**

}
// Treat favicons as non-critical resources
if (request.mimeType === 'image/x-icon' ||
(request.parsedURL && request.parsedURL.lastPathComponent === 'favicon.ico')) {
return false;
}
return includes(['VeryHigh', 'High', 'Medium'], request.priority());

@@ -41,0 +48,0 @@ }

@@ -211,7 +211,9 @@ /**

const hostname = parsedResourceURL.hostname;
let file = parsedResourceURL.path
// Remove any query strings.
.replace(/\?.*/, '')
// Grab the last two parts of the path.
// Handle 'about:*' URLs specially since they have no path.
let file = parsedResourceURL.protocol === 'about:' ? parsedResourceURL.href :
// Otherwise, remove any query strings from the path.
parsedResourceURL.path.replace(/\?.*/, '')
// And grab the last two parts.
.split('/').slice(-2).join('/');
if (file.length > MAX_FILENAME_LENGTH) {

@@ -218,0 +220,0 @@ file = file.slice(0, MAX_FILENAME_LENGTH) + '...';

@@ -80,3 +80,3 @@ /**

fs.writeFileSync(artifactsFilename, stringify(artifacts));
log.log('info', 'artifacts file saved to disk', artifactsFilename);
log.log('artifacts file saved to disk', artifactsFilename);
}

@@ -95,7 +95,7 @@

fs.writeFileSync(traceFilename + '.trace.json', stringify(assets.traceData, null, 2));
log.log('info', 'trace file saved to disk', traceFilename);
log.log('trace file saved to disk', traceFilename);
const screenshotsFilename = getFilenamePrefix(options);
fs.writeFileSync(screenshotsFilename + '.screenshots.html', assets.html);
log.log('info', 'screenshots saved to disk', screenshotsFilename);
log.log('screenshots saved to disk', screenshotsFilename);
}

@@ -102,0 +102,0 @@

@@ -19,7 +19,37 @@ /**

const npmlog = require('npmlog');
const debug = require('debug');
// Use `npmlog` in node, `console` in browser and electron.
const isNode = !!process && !process.browser && !process.versions.electron;
function setLevel(level) {
if (level === 'verbose') {
debug.enable('*');
} else if (level === 'error') {
debug.enable('*:error');
} else {
debug.enable('*, -*:verbose');
}
}
module.exports = isNode ? npmlog : console;
const loggers = {};
function _log(title, logargs) {
const args = [...logargs].slice(1);
if (!loggers[title]) {
loggers[title] = debug(title);
}
return loggers[title](...args);
}
module.exports = {
setLevel,
log(title) {
return _log(title, arguments);
},
warn(title) {
return _log(`${title}:warn`, arguments);
},
error(title) {
return _log(`${title}:error`, arguments);
},
verbose(title) {
return _log(`${title}:verbose`, arguments);
}
};

@@ -128,9 +128,18 @@ /**

* durations.
* If one of the durations overlaps the end of the window, the full
* duration should be in the duration array, but the length not included
* within the window should be given as `clippedLength`. For instance, if a
* 50ms duration occurs 10ms before the end of the window, `50` should be in
* the `durations` array, and `clippedLength` should be set to 40.
* @see https://docs.google.com/document/d/18gvP-CBA2BiBpi3Rz1I1ISciKGhniTSZ9TY0XCnXS7E/preview
* @param {!Array<number>} durations Array of durations, sorted in ascending order.
* @param {number} totalTime Total time (in ms) of interval containing durations.
* @param {!Array<number>} percentiles Array of percentiles of interest, in ascending order.
* @param {number=} clippedLength Optional length clipped from a duration overlapping end of window. Default of 0.
* @return {!Array<{percentile: number, time: number}>}
* @private
*/
static _riskPercentiles(durations, totalTime, percentiles) {
static _riskPercentiles(durations, totalTime, percentiles, clippedLength) {
clippedLength = clippedLength || 0;
let busyTime = 0;

@@ -140,2 +149,3 @@ for (let i = 0; i < durations.length; i++) {

}
busyTime -= clippedLength;

@@ -146,5 +156,11 @@ // Start with idle time already complete.

let cdfTime = completedTime;
let remainingCount = durations.length + 1;
const results = [];
let durationIndex = -1;
let remainingCount = durations.length + 1;
if (clippedLength > 0) {
// If there was a clipped duration, one less in count since one hasn't started yet.
remainingCount--;
}
// Find percentiles of interest, in order.

@@ -155,9 +171,16 @@ for (let percentile of percentiles) {

const percentileTime = percentile * totalTime;
while (cdfTime < percentileTime && remainingCount > 1) {
while (cdfTime < percentileTime && durationIndex < durations.length) {
completedTime += duration;
remainingCount--;
duration = durations[durations.length - remainingCount];
remainingCount -= (duration < 0 ? -1 : 1);
if (clippedLength > 0 && clippedLength < durations[durationIndex + 1]) {
duration = -clippedLength;
clippedLength = 0;
} else {
durationIndex++;
duration = durations[durationIndex];
}
// Calculate value of CDF (multiplied by totalTime) for the end of this duration.
cdfTime = completedTime + duration * remainingCount;
cdfTime = completedTime + Math.abs(duration) * remainingCount;
}

@@ -178,2 +201,3 @@

* selected percentiles within a window of the main thread.
* @see https://docs.google.com/document/d/18gvP-CBA2BiBpi3Rz1I1ISciKGhniTSZ9TY0XCnXS7E/preview
* @param {!traceviewer.Model} model

@@ -191,5 +215,8 @@ * @param {!Array<!Object>} trace

const totalTime = endTime - startTime;
if (percentiles) {
percentiles.sort((a, b) => a - b);
} else {
percentiles = [0.5, 0.75, 0.9, 0.99, 1];
}
percentiles = percentiles || [0.5, 0.75, 0.9, 0.99, 1];
// Find the main thread.

@@ -204,2 +231,3 @@ const startEvent = trace.find(event => {

const durations = [];
let clippedLength = 0;
mainThread.sliceGroup.topLevelSlices.forEach(slice => {

@@ -211,3 +239,16 @@ // Discard slices outside range.

durations.push(slice.duration);
// Clip any at edges of range.
let duration = slice.duration;
let sliceStart = slice.start;
if (sliceStart < startTime) {
// Any part of task before window can be discarded.
sliceStart = startTime;
duration = slice.end - sliceStart;
}
if (slice.end > endTime) {
// Any part of task after window must be clipped but accounted for.
clippedLength = duration - (endTime - sliceStart);
}
durations.push(duration);
});

@@ -217,3 +258,3 @@ durations.sort((a, b) => a - b);

// Actual calculation of percentiles done in _riskPercentiles.
return TraceProcessor._riskPercentiles(durations, totalTime, percentiles);
return TraceProcessor._riskPercentiles(durations, totalTime, percentiles, clippedLength);
}

@@ -220,0 +261,0 @@

@@ -5,3 +5,3 @@ {

"description": "Lighthouse core",
"main": "./module/index.js",
"main": "./index.js",
"engines": {

@@ -34,3 +34,4 @@ "node": ">=5"

"chrome-remote-interface": "^0.11.0",
"devtools-timeline-model": "1.1.4",
"debug": "^2.2.0",
"devtools-timeline-model": "1.1.6",
"gl-matrix": "2.3.2",

@@ -40,5 +41,4 @@ "handlebars": "^4.0.5",

"jszip": "2.6.0",
"npmlog": "^2.0.3",
"semver": ">=4.3.3",
"speedline": "^0.1.2"
"speedline": "0.2.2"
},

@@ -45,0 +45,0 @@ "devDependencies": {

@@ -16,23 +16,30 @@ /**

*/
'use strict';
const Audit = require('../../audits/is-on-https.js');
const assert = require('assert');
/* global describe, it*/
/* eslint-env mocha */
describe('Security: HTTPS audit', () => {
it('fails when no input present', () => {
return assert.equal(Audit.audit({}).value, false);
});
it('fails when not on HTTPS', () => {
return assert.equal(Audit.audit({
HTTPS: false
}).value, false);
const debugString = 'Error string';
const result = Audit.audit({
HTTPS: {
value: false,
debugString
}
});
assert.strictEqual(result.value, false);
assert.strictEqual(result.debugString, debugString);
});
it('passes when on HTTPS', () => {
return assert.equal(Audit.audit({
HTTPS: true
}).value, true);
const result = Audit.audit({
HTTPS: {
value: true
}
});
assert.strictEqual(result.value, true);
});
});

@@ -24,3 +24,7 @@ /**

return Core
.audit([{}], ['is-on-https'])
.audit({
HTTPS: {
value: false
}
}, ['is-on-https'])
.then(modifiedResults => {

@@ -27,0 +31,0 @@ assert.ok(Array.isArray(modifiedResults));

@@ -290,2 +290,23 @@ /**

it('discards favicons as non-critical', () => {
const networkRecords = mockTracingData([HIGH, HIGH, HIGH], [[0, 1], [0, 2]]);
// 2nd record is a favicon
networkRecords[1].url = 'https://example.com/favicon.ico';
networkRecords[1].parsedURL = {
lastPathComponent: 'favicon.ico'
};
// 3rd record is also a favicon
networkRecords[2].mimeType = 'image/x-icon';
Gatherer.afterPass(null, {networkRecords});
const criticalChains = Gatherer.artifact;
assert.deepEqual(criticalChains, {
0: {
request: constructEmptyRequest(),
children: {}
}
});
});
it('handles non-existent nodes when building the tree', () => {

@@ -292,0 +313,0 @@ const networkRecords = mockTracingData([HIGH, HIGH], [[0, 1]]);

@@ -53,2 +53,12 @@ /**

children: {}
},
3: {
request: {
endTime: 18,
responseReceivedTime: 16,
startTime: 13,
url: 'about:blank',
transferSize: 1
},
children: {}
}

@@ -59,3 +69,3 @@ }

/* global describe, it */
/* eslint-env mocha */

@@ -79,2 +89,3 @@ describe('CRC Formatter', () => {

assert.ok(truncatedURLRegExp.test(output));
assert.ok(/about:blank/.test(output));
});

@@ -81,0 +92,0 @@

@@ -29,3 +29,3 @@ /**

* @param {!Array<number>} percentiles
* @param {!array<number>} times
* @param {!Array<number>} times
* @return {!Array<{percentile: number, time: number}>}

@@ -75,3 +75,72 @@ */

});
// Three tasks of one second each, all within a five-second window.
// Mean Queueing Time of 300ms.
it('correctly calculates percentiles of three one-second tasks in a five-second window', () => {
const results = TracingProcessor._riskPercentiles([1000, 1000, 1000], 5000,
defaultPercentiles, 0);
// Round to hundredths to simplify floating point comparison.
results.forEach(result => {
result.time = Number(result.time.toFixed(2));
});
const expected = createRiskPercentiles(defaultPercentiles,
[16, 16, 182.67, 599.33, 849.33, 999.33, 1016]);
assert.deepEqual(results, expected);
});
it('correctly calculates percentiles of tasks with a clipped task', () => {
const results = TracingProcessor._riskPercentiles([10, 20, 50, 60, 90, 100], 300,
defaultPercentiles, 30);
// Round to hundredths to simplify floating point comparison.
results.forEach(result => {
result.time = Number(result.time.toFixed(2));
});
const expected = createRiskPercentiles(defaultPercentiles,
[16, 32.25, 53.5, 74.33, 96, 113, 116]);
assert.deepEqual(results, expected);
});
// One 20 second long task over three five-second windows.
it('correctly calculates percentiles of single task over multiple windows', () => {
// Starts 3 seconds into the first window. Mean Queueing Time = 7600ms.
const TASK_LENGTH = 20000;
let results1 = TracingProcessor._riskPercentiles([TASK_LENGTH], 5000,
defaultPercentiles, TASK_LENGTH - 2000);
const expected1 = createRiskPercentiles(defaultPercentiles,
[16, 16, 16, 18766, 19516, 19966, 20016]);
assert.deepEqual(results1, expected1);
// Starts 2 seconds before and ends 13 seconds after. Mean Queueing Time = 15500ms.
const results2 = TracingProcessor._riskPercentiles([TASK_LENGTH - 2000], 5000,
defaultPercentiles, TASK_LENGTH - 7000);
const expected2 = createRiskPercentiles(defaultPercentiles,
[16, 14266, 15516, 16766, 17516, 17966, 18016]);
assert.deepEqual(results2, expected2);
// Starts 17 seconds before and ends 3 seconds into the window. Mean Queueing Time = 900ms.
const results3 = TracingProcessor._riskPercentiles([TASK_LENGTH - 17000], 5000,
defaultPercentiles, 0);
const expected3 = createRiskPercentiles(defaultPercentiles,
[16, 16, 516, 1766, 2516, 2966, 3016]);
assert.deepEqual(results3, expected3);
});
it('correctly calculates with a task shorter than the clipped length of another', () => {
const results = TracingProcessor._riskPercentiles([40, 100], 100,
defaultPercentiles, 50);
const expected = createRiskPercentiles(defaultPercentiles,
[16, 31, 56, 91, 106, 115, 116]);
assert.deepEqual(results, expected);
});
it('correctly calculates with a task clipped completely', () => {
const results = TracingProcessor._riskPercentiles([40, 100], 100,
defaultPercentiles, 100);
const expected = createRiskPercentiles(defaultPercentiles,
[16, 16, 16, 31, 46, 55, 56]);
assert.deepEqual(results, expected);
});
});
});

@@ -23,2 +23,3 @@ /**

const config = require('../../../lighthouse-core/config/default.json');
const log = require('../../../lighthouse-core/lib/log');

@@ -40,2 +41,5 @@ window.createPageAndPopulate = function(results) {

window.runAudits = function(options) {
// Default to 'info' logging level.
log.setLevel('info');
const driver = new ExtensionProtocol();

@@ -42,0 +46,0 @@

@@ -117,3 +117,2 @@ // generated on 2016-03-19 using generator-chrome-extension 0.5.4

})
.ignore('npmlog')
.ignore('chrome-remote-interface');

@@ -120,0 +119,0 @@

{
"name": "lighthouse",
"version": "1.0.2",
"version": "1.0.3",
"description": "Lighthouse",

@@ -11,9 +11,6 @@ "main": "./lighthouse-core/module/index.js",

"scripts": {
"//":
"// dependency installation",
"//": "// passing through tasks to core",
"postinstall": "npm run core-install && npm run extension-install",
"core-install": "npm --prefix ./lighthouse-core install ./lighthouse-core",
"extension-install": "npm --prefix ./lighthouse-extension install ./lighthouse-extension",
"//":
"// global tasks",
"lint": "eslint .",

@@ -24,9 +21,5 @@ "smoke": "lighthouse-cli/scripts/run-smoke-tests.sh",

"start": "node ./lighthouse-cli/index.js",
"//":
"// test",
"test": "npm run lint --silent && npm run unit && npm run closure",
"cli-unit": "mocha $(find lighthouse-cli/test -name '*.js') --timeout 60000",
"unit": "npm run cli-unit && npm --prefix ./lighthouse-core run unit",
"//":
"// passing through tasks to core",
"closure": "npm --prefix ./lighthouse-core run closure",

@@ -44,2 +37,3 @@ "watch": "npm --prefix ./lighthouse-core run watch",

"dependencies": {
"semver": ">=4.3.3",
"yargs": "3.30.0"

@@ -46,0 +40,0 @@ },

@@ -98,14 +98,7 @@ # lighthouse

Moreover…
##### Internal module graph
![graph of lighthouse-core module dependencies](https://cloud.githubusercontent.com/assets/39191/16317303/54a25e20-3982-11e6-9374-dd3c24b70468.png)
<small><code>npm install -g js-vd; vd --exclude "node_modules|third_party" lighthouse-core/ > graph.html</code></small>
* `/core.js` does the gathering, auditing and aggregation
* `/runner.js` is the shared handler (for both module & extension) that needs to be given a driver, and sets up the core to do its job
* `/module/index` is the require('lighthouse') file so you can use it in Node, and it uses the runner
```
module/index \
----- Runner ----- Core [Gather / Audit / Aggregate]
extension /
```
### Protocol

@@ -112,0 +105,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc