Comparing version 4.3.0 to 4.4.0
79
cmd.js
@@ -16,3 +16,3 @@ #!/usr/bin/env node | ||
0x ${version} | ||
0x [flags] -- node [nodeFlags] script.js [scriptFlags] | ||
@@ -28,6 +28,17 @@ | ||
}) | ||
} else module.exports = cmd | ||
} else { | ||
module.exports = cmd | ||
} | ||
async function cmd (argv, banner = defaultBanner) { | ||
var args = minimist(argv, { | ||
if (semver.lt(process.version, '8.5.0') === true) { | ||
throw Error( | ||
`Node version unsupported. Current Node version is ${process.version}\n` + | ||
'Support extends from Node 8.5.0 and above.\n\n' + | ||
' npm i -g 0x@3 for Node 6.x.x – 8.4.0\n' + | ||
' npm i -g 0x@2 for Node 4\n' | ||
) | ||
} | ||
const args = minimist(argv, { | ||
stopEarly: true, | ||
@@ -60,11 +71,2 @@ '--': true, | ||
if (semver.lt(process.version, '8.5.0') === true) { | ||
throw Error( | ||
'Node version unsupported. Current Node version is ' + process.version + '\n' + | ||
'Support extends from Node 8.5.0 and above.\n\n' + | ||
' npm i -g 0x@3 for Node 6.x.x – 8.4.0\n' + | ||
' npm i -g 0x@2 for Node 4\n' | ||
) | ||
} | ||
if (args.help || argv.length === 0) { | ||
@@ -75,18 +77,27 @@ process.stdout.write(banner) | ||
if (args.version) return console.log('0x ' + version) | ||
if (args.version) { | ||
return console.log(`0x ${version}`) | ||
} | ||
const status = createStatus(args) | ||
const { pathToNodeBinary, subprocessArgv } = parseSubprocessCommand(args) | ||
args.workingDir = process.cwd() | ||
args.status = status | ||
const { pathToNodeBinary, subprocessArgv } = parseSubprocessCommand(args) | ||
args.argv = subprocessArgv | ||
args.pathToNodeBinary = pathToNodeBinary | ||
if (args.visualizeOnly) status(`Creating flamegraph from ${args.visualizeOnly}`) | ||
if (args.visualizeOnly) { | ||
status(`Creating flamegraph from ${args.visualizeOnly}`) | ||
} | ||
const assetPath = await zeroEks(args) | ||
if (args.collectOnly) status(`Stats collected in folder file://${assetPath}\n`) | ||
else { | ||
status('Flamegraph generated in\n' + assetPath + '\n') | ||
if (args.open) launch(assetPath, {wait: false}) | ||
if (args.collectOnly) { | ||
status(`Stats collected in folder file://${assetPath}\n`) | ||
} else { | ||
status(`Flamegraph generated in\n${assetPath}\n`) | ||
if (args.open) { | ||
launch(assetPath, { wait: false }) | ||
} | ||
} | ||
@@ -99,11 +110,14 @@ | ||
const dashDash = args['--'] | ||
if (dashDash[0] && dashDash[0][0] === '-') { | ||
throw Error(`The node binary must immediately follow double dash (--) | ||
0x [flags] -- node [nodeFlags] script.js [scriptFlags] | ||
`) | ||
} | ||
var pathToNodeBinary = false | ||
var subprocessArgv = args._ | ||
if (dashDash[0]) { | ||
if (dashDash[0][0] !== 'node') pathToNodeBinary = dashDash[0] | ||
let pathToNodeBinary = process.argv[0] | ||
let subprocessArgv = args._ | ||
if (dashDash.length !== 0) { | ||
const dashEntry = dashDash[0][0]; | ||
if (dashEntry === '-') { | ||
throw Error( | ||
'The node binary must immediately follow double dash (--)\n' + | ||
'0x [flags] -- node [nodeFlags] script.js [scriptFlags]' | ||
) | ||
} | ||
pathToNodeBinary = dashDash[0] | ||
dashDash.shift() | ||
@@ -115,7 +129,8 @@ subprocessArgv = dashDash | ||
function createStatus ({silent, quiet}) { | ||
const statusStream = process.stderr | ||
if (quiet || silent) return () => {} | ||
const status = sll(statusStream) | ||
function createStatus ({ silent, quiet }) { | ||
if (quiet || silent) { | ||
return () => {} | ||
} | ||
const status = sll(process.stderr) | ||
return hasUnicode ? (s) => status(`🔥 ${s}`) : status | ||
} |
33
index.js
@@ -7,2 +7,3 @@ 'use strict' | ||
const fs = require('fs') | ||
const { promisify } = require('util') | ||
const validate = require('./lib/validate')(require('./schema.json')) | ||
@@ -17,2 +18,4 @@ const traceStacksToTicks = require('./lib/trace-stacks-to-ticks') | ||
const fsWriteFilePromise = promisify(fs.writeFile) | ||
module.exports = zeroEks | ||
@@ -31,3 +34,3 @@ | ||
args.title = args.title || 'node ' + args.argv.join(' ') | ||
args.title = args.title || `node ${args.argv.join(' ')}` | ||
const binary = args.pathToNodeBinary | ||
@@ -41,4 +44,2 @@ var { ticks, pid, folder, inlined } = await startProcessAndCollectTraceData(args, binary) | ||
fs.writeFileSync(`${folder}/meta.json`, JSON.stringify({...args, inlined})) | ||
if (collectOnly === true) { | ||
@@ -52,3 +53,6 @@ debug('collect-only mode bailing on rendering') | ||
try { | ||
const file = await generateFlamegraph({...args, ticks, inlined, pid, folder}) | ||
const [file] = await Promise.all([ | ||
generateFlamegraph({...args, ticks, inlined, pid, folder}), | ||
fsWriteFilePromise(`${folder}/meta.json`, JSON.stringify({...args, inlined})) | ||
]) | ||
return file | ||
@@ -76,13 +80,8 @@ } catch (err) { | ||
async function generateFlamegraph (opts) { | ||
try { | ||
const file = await render(opts) | ||
tidy() | ||
return file | ||
} catch (err) { | ||
tidy() | ||
throw err | ||
} | ||
const file = await render(opts) | ||
tidy() | ||
return file | ||
} | ||
async function visualize ({ visualizeOnly, treeDebug, workingDir, title, mapFrames, phase, open, name }) { | ||
async function visualize ({ visualizeOnly, treeDebug, workingDir, title, mapFrames, open, name, pathToNodeBinary }) { | ||
try { | ||
@@ -117,3 +116,3 @@ const folder = isAbsolute(visualizeOnly) | ||
const ticks = (srcType === 'v8') | ||
? await v8LogToTicks(src) | ||
? await v8LogToTicks(src, pathToNodeBinary) | ||
: traceStacksToTicks(src) | ||
@@ -144,6 +143,8 @@ | ||
throw Error('Invalid data path provided (unable to access/does not exist)') | ||
} else if (e.code === 'ENOTDIR') { | ||
} | ||
if (e.code === 'ENOTDIR') { | ||
throw Error('Invalid data path provided (not a directory)') | ||
} else throw e | ||
} | ||
throw e | ||
} | ||
} |
@@ -11,2 +11,3 @@ 'use strict' | ||
const envString = require('env-string') | ||
const makeDir = require('make-dir') | ||
@@ -35,3 +36,3 @@ module.exports = { | ||
if (code === 0 || code === null) resolve(code, signal) | ||
else reject(Object.assign(Error(`onPort command failed with code: ${code}`), { code })) | ||
else reject(Object.assign(Error(`onPort command failed with code: ${code}`), { code })) | ||
}) | ||
@@ -42,20 +43,10 @@ }) | ||
function getTargetFolder ({outputDir, workingDir, name, pid}) { | ||
name = (outputDir || '{pid}.0x').replace('{pid}', pid || 'UNKNOWN_PID') | ||
.replace('{timestamp}', Date.now()) | ||
.replace('{cwd}', workingDir) | ||
.replace('{name}', name) | ||
name = (outputDir || '{pid}.0x').replace(/{pid}/g, pid || 'UNKNOWN_PID') | ||
.replace(/{timestamp}/g, Date.now()) | ||
.replace(/{cwd}/g, workingDir) | ||
.replace(/{name}/g, name) | ||
const folder = path.resolve(workingDir, name) | ||
makeDir.sync(folder) | ||
try { | ||
fs.accessSync(folder) | ||
} catch (e) { | ||
if (e.code === 'ENOENT') { | ||
fs.mkdirSync(folder) | ||
} else { | ||
// function is always used within async/await or promise - fine to throw | ||
throw e | ||
} | ||
} | ||
return folder | ||
@@ -62,0 +53,0 @@ } |
@@ -12,5 +12,5 @@ 'use strict' | ||
function v8LogToTicks (isolateLogPath) { | ||
function v8LogToTicks (isolateLogPath, node) { | ||
const isJson = extname(isolateLogPath) === '.json' | ||
const sp = isJson || spawn(process.argv[0], [ | ||
const sp = isJson || spawn(node, [ | ||
'--prof-process', '--preprocess', '-j', isolateLogPath | ||
@@ -21,6 +21,6 @@ ], {stdio: ['ignore', 'pipe', 'pipe']}) | ||
if (!isJson) { | ||
// unknown code state errors are mostly harmless, | ||
// unknown code state errors are mostly harmless, | ||
// and not fixable within 0x at the moment (because | ||
// it's an error in the V8 internal tick profiler) | ||
// ignore them. | ||
// ignore them. | ||
const ignore = /unknown code state:/ | ||
@@ -27,0 +27,0 @@ pump(sp.stderr, through((errMsg, _, cb) => { |
{ | ||
"name": "0x", | ||
"version": "4.3.0", | ||
"version": "4.4.0", | ||
"description": "🔥 single-command flamegraph profiling 🔥", | ||
@@ -39,2 +39,3 @@ "main": "index.js", | ||
"jsonstream2": "^1.1.1", | ||
"make-dir": "^1.3.0", | ||
"minimist": "^1.2.0", | ||
@@ -41,0 +42,0 @@ "morphdom": "^2.3.3", |
@@ -116,3 +116,3 @@ 'use strict' | ||
return { | ||
ticks: await v8LogToTicks(isolateLogPath), | ||
ticks: await v8LogToTicks(isolateLogPath, node), | ||
inlined: inlined, | ||
@@ -119,0 +119,0 @@ pid: proc.pid, |
@@ -22,4 +22,4 @@ 'use strict' | ||
<style> | ||
button:focus { outline:0; } | ||
rect:hover {opacity: 0.9} | ||
button:focus { outline:0; } | ||
rect:hover {opacity: 0.9} | ||
</style> | ||
@@ -26,0 +26,0 @@ </head> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
87556
1755
27
+ Addedmake-dir@^1.3.0
+ Addedmake-dir@1.3.0(transitive)
+ Addedpify@3.0.0(transitive)