diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 8c95013..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -**/format/html/* -.coverage_data/* -node_modules/* -.coverignore -npm-debug.log -cover_html/* -.coverage_debug/* \ No newline at end of file diff --git a/README.markdown b/README.markdown deleted file mode 100644 index 1987f5a..0000000 --- a/README.markdown +++ /dev/null @@ -1,96 +0,0 @@ -## Cover - Native JavaScript Code Coverage - -Cover gives you the ability to collect code-coverage for your projects, using -whatever unit test framework you want, and all using native JavaScript. It also -comes bundled with pre-defined reporters, such as HTML and CLI output, so you -can easily see where you are missing coverage. - -### Standing on the shoulders of giants - -I would be amiss to not mention that the hard work in this library was -by [Chris Dickinson] with his work on [runforcover]. In reality, Cover is -a fork of runforcover, fixing some of the issues and making it more usable. - -The original version of Cover used [substack]'s excellent [bunker] library, -but it has recently been moved to using [esprima] and a new code homegrown -instrumentation library. - -### Known Issues - -There are currently a few known issues that I am working on: - -1. If you use 'global' to pass state between modules (mocha does this, for -example), then you might run into issues. Cover runs modules as if they -were executed with `NODE_MODULE_CONTEXTS` was set. - -2. If you start new node processes, Cover won't work with those, as -it instruments by hooking into `require`. - -### Usage - -Using Cover is simple. Simply install it globally: - -> npm install cover -g - -And then, run it - -> cover run mytests.js - -Want to pass some arguments to your test? No problem (note the `--`): - -> cover run mytests.js -- --arg1 --arg2=foo - - Once you've run your tests, it will create a directory with coverage data in it. - If you want to see the coverage report, simply run: - - > cover report - - which will output the report to the CLI. Want to get an HTML report? - - > cover report html - - This will create a `cover_html` directory with the coverage information. - -### Configuration - -Cover reads from a `.coverrc` file in your project directory, and it comes -with sensible defaults. Here are the defaults that it uses: - - { - "formatter": "cli", - "ignore": ".coverignore", - - "prefix": "coveragefile_", // Prefix for coverage data files - "dataDirectory": ".coverage_data", // Directory to put coverage files in - - "debugDirectory": ".coverage_debug", // Directory to put instrumented files in - - "modules": false, // Whether or not to cover node_modules directory - - // Formatter-specific info - "html" : { - "directory": "cover_html", // Directory to write HTML files too - "generateIndex": true // Whether to generate an index.html file - }, - - "json": { - } - } - -You can also specify which files to ignore using .coverignore. Here is the one used -for Cover itself: - - node_modules - -You can specify both files and directories in the `.coverignore` file. - -If you have a custom path for your configuration files, you can specify this -on the command line: - -> cover --config path/to/config --ignore path/to/ignore run myfile.js - -[esprima]: http://www.esprima.org -[substack]: https://github.com/substack -[bunker]: https://github.com/substack/node-bunker -[Chris Dickinson]: https://github.com/chrisdickinson -[runforcover]: https://github.com/chrisdickinson/node-runforcover diff --git a/bin/.coverrc b/bin/.coverrc deleted file mode 100644 index 5d4d7b4..0000000 --- a/bin/.coverrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "formatter": "cli", - "ignore": ".coverignore", - - "prefix": "coveragefile_", // Prefix for coverage data files - "dataDirectory": ".coverage_data", // Directory to put coverage files in - - "debugDirectory": ".coverage_debug", // Directory to put instrumented files in - - "modules": false, // Whether or not to cover node_modules directory - - // Formatter-specific info - "html" : { - "directory": "cover_html", // Directory to write HTML files too - "generateIndex": true // Whether to generate an index.html file - }, - - "json": { - } -} \ No newline at end of file diff --git a/bin/cover b/bin/cover deleted file mode 100755 index 86508c5..0000000 --- a/bin/cover +++ /dev/null @@ -1,769 +0,0 @@ -#!/usr/bin/env node - -// Copyright 2011 Itay Neeman -// -// Licensed under the MIT License - -// TODO: - -(function() { - var fs = require('fs'); - var path = require('path'); - var vm = require("vm"); - var crypto = require('crypto'); - var Module = require('module').Module; - var _ = require('underscore'); - var _s = require('underscore.string'); - var which = require('which').sync; - var commander = require('../contrib/commander'); - var Table = require('../contrib/cli-table'); - var pkg = require('../package.json'); - - var exists = fs.existsSync || path.existsSync; - - var patch_console = require('../utils/console'); - var cover = require("../index.js"); - - // Store the initial CWD, to harden us against process.chdir - var CWD = path.resolve(process.cwd()); - - // Get a list of the built-in reporters - var reporterOptions = "[" + _.keys(cover.reporters).join(",") + "]"; - - /* ====== Utilities ====== */ - - // Delete a directory recursively - var rmdirRecursiveSync = function(dirPath) { - var files = fs.readdirSync(dirPath); - - for(var i = 0; i < files.length; i++) { - var filePath = path.join(dirPath, files[i]); - var file = fs.statSync(filePath); - - if (file.isDirectory()) { - rmdirRecursiveSync(filePath); - } - else { - fs.unlinkSync(filePath); - } - } - - fs.rmdirSync(dirPath); - }; - - /* ====== Config/Ignore File Handling ====== */ - - // Default config - var defaultConfigPath = path.join(path.resolve(__dirname), ".coverrc"); - var defaultConfig = {}; - - var removeJSONComments = function(str) { - str = str || ''; - str = str.replace(/\/\*[\s\S]*(?:\*\/)/g, ''); //everything between "/* */" - str = str.replace(/\/\/[^\n\r]*/g, ''); //everything after "//" - return str; - }; - - var readIgnoreFile = function(ignorePath, ignoreModules) { - var ignore = {}; - - // Get the full path relative to the CWD - var fullIgnorePath = path.resolve(CWD, ignorePath); - if (exists(fullIgnorePath)) { - // If we found an ignore file, read it in - var ignoreContents = fs.readFileSync(fullIgnorePath, "utf-8"); - try { - // Note that directory fo the ignore path - var dir = path.dirname(fullIgnorePath); - var ignores = ignoreContents.split("\n"); - - // For each line (ignoring blank ones), get the full path, - // and add it to our ignore list. - for(var i = 0; i < ignores.length; i++) { - if (ignores[i].trim() === "") { - continue; - } - - var filePath = path.resolve(dir, ignores[i].trim()); - ignore[path.resolve(dir, filePath)] = true; - } - } - catch (ex) { - throw new Error("There was a problem parsing your .coverignore file at: " + ignorePath); - } - } - - return ignore; - }; - - var readConfigFile = function(configFile) { - var config = {} - - // Get the full path relative to the CWD - configFile = path.resolve(CWD, configFile); - if (!exists(configFile)) { - configFile = defaultConfigPath; - } - - // Remove any comments from the JSON - var configContents = removeJSONComments(fs.readFileSync(path.resolve(configFile), "utf-8")); - - try { - // If there is no content, we'll just add an empty object - if (configContents.trim() === "") { - configContents = "{}"; - } - - // Parse it and copy in the defaults - var rawConfig = JSON.parse(configContents); - for(var key in defaultConfig) { - config[key] = defaultConfig[key]; - } - - // Override the defaults with specific ones. - for(var key in rawConfig) { - config[key] = rawConfig[key]; - } - } - catch (ex) { - throw new Error("There was a problem parsing your .coverrc file at: " + configFile); - } - - return config; - }; - - var getOptionsAndIgnore = function(cmdline, options) { - options = options || {}; - - // Get configuration - var config = {}; - if (cmdline.config || ".coverrc") { - if (_.isObject(cmdline.config)) { - config = cmdline.config; - } - else { - config = readConfigFile(cmdline.config || ".coverrc"); - } - } - - // Get ignore - var ignore = {}; - if (cmdline.ignore || config.ignore || ".coverignore") { - if (_.isObject(cmdline.ignore)) { - ignore = cmdline.ignore; - } - else { - ignore = readIgnoreFile(cmdline.ignore || config.ignore || ".coverignore"); - } - } - - // If we didn't override it on the command line and the - // coverrc file says to ingore node_modules, then ignore - // it - if (options.modules !== true && config.modules === false) { - ignore[path.resolve(CWD, "node_modules")] = true; - } - - return { - config: config, - ignore: ignore - } - }; - - defaultConfig = readConfigFile(defaultConfigPath); - - /* ====== Context and Execution Handling ====== */ - - // Run a file with coverage enabled - var runFile = function(file, options, ignore, debug) { - if (!exists(file)) { - try { - file = which(file); - } - catch(ex) { - console.log("Could not find file: '" + file + "' -- exiting..."); - return null; - } - } - else { - file = path.resolve(file); - } - - var coverage = cover.cover(null, ignore, debug); - - process.nextTick(function() { - try { - // Load up the new argv - options = options || []; - process.argv = ["node", file].concat(options) - - // Load the file as the main module - Module.runMain(file, null, true) - } - catch(ex) { - console.log(ex.stack); - } - }); - - return coverage; - }; - - /* ====== Save/Load Coverage Data ====== */ - var saveCoverageData = function(coverageData, configs, noPrecombine) { - if (!noPrecombine) { - savePrecombinedCoverageData(coverageData, configs); - } - - // Setup the information we're going to save - var files = {}; - var toSave = { - version: pkg.version, - files: files - }; - - _.each(coverageData, function(fileData, fileName, lst) { - // For each file, we hash the source to get a "version ID" - // for it - var stats = fileData.stats(); - var fileSource = stats.source; - var md5 = crypto.createHash('md5'); - md5.update(fileSource); - var hash = md5.digest('hex'); - - // We also save the stats and the hash, - // which is everything we need in order - // to be able to generate reports - files[fileName] = { - stats: stats, - hash: hash - } - }); - - // Turn it into JSON and write it out - var data = JSON.stringify(toSave); - - // Get the ID for this data (md5 hash) - var dataMd5 = crypto.createHash('md5'); - dataMd5.update(data); - var dataHash = dataMd5.digest('hex'); - - // Make the directory - var dataDirectory = path.join(CWD, configs.dataDirectory); - if (!exists(dataDirectory)) { - fs.mkdirSync(dataDirectory, "0755"); - } - - // Write out the file - var dataFilename = path.join(dataDirectory, configs.prefix + dataHash); - fs.writeFileSync(dataFilename, data); - }; - - var savePrecombinedCoverageData = function(coverageData, configs) { - // Setup the information we're going to save - var files = {}; - var toSave = { - version: "0.2.0", - files: files - }; - - var coverageStore = require('../coverage_store'); - - _.each(coverageData, function(fileData, fileName, lst) { - var store = coverageStore.getStore(fileName); - - // For each file, we hash the source to get a "version ID" - // for it - var fileSource = fileData.source; - var md5 = crypto.createHash('md5'); - md5.update(fileSource); - var hash = md5.digest('hex'); - - // We also save the stats and the hash, - // which is everything we need in order - // to be able to generate reports - files[fileName] = { - nodes: store.nodes, - blocks: store.blocks, - hash: hash, - instrumentor: fileData.instrumentor.objectify() - } - }); - - // Turn it into JSON and write it out - var data = JSON.stringify(toSave); - - // Get the ID for this data (md5 hash) - var dataMd5 = crypto.createHash('md5'); - dataMd5.update(data); - var dataHash = dataMd5.digest('hex'); - - // Make the directory - var dataDirectory = path.join(CWD, configs.dataDirectory); - if (!exists(dataDirectory)) { - fs.mkdirSync(dataDirectory, "0755"); - } - - // Write out the file - var dataFilename = path.join(dataDirectory, "precombined_" + configs.prefix + dataHash); - fs.writeFileSync(dataFilename, data); - }; - - var loadCoverageData = function(filename, configs) { - var dataDirectory = configs.dataDirectory; - var dataPrefix = configs.prefix; - - if (!filename) { - // If we weren't given a file, try and read it from the data directory. - var filesInDataDirectory = fs.readdirSync(dataDirectory); - var matchingFiles = _.filter(filesInDataDirectory, function(file) { return _s.startsWith(file, dataPrefix); }); - if (matchingFiles.length > 1) { - // If there is more than one file, we'll use the last modified one. - var latestTime = 0; - for(var i = 0; i < matchingFiles.length; i++) { - var fileLatest = fs.statSync(path.join(dataDirectory, matchingFiles[i])).mtime; - if (fileLatest > latestTime) { - latestTime = fileLatest; - filename = matchingFiles[i]; - } - } - } - else if (matchingFiles.length === 1) { - // If there was exactly one file, we'll use that one - filename = matchingFiles[0]; - } - else if (matchingFiles.length === 0) { - // If there was no file, error. - console.error("Could not find a coverage data file. Please specify one."); - process.exit(1); - } - - // Note the full path to the file - filename = path.join(dataDirectory, filename); - } - - // If it doesn't exist, then error out - if (!exists(filename)) { - console.error("Coverage data file does not exist: " + filename); - process.exit(1); - } - - // Read the file - var data = fs.readFileSync(filename, "utf-8"); - var coverageData = JSON.parse(data); - - var overall = { - missing : 0, - seen : 0, - total : 0, - blocks : { - total : 0, - seen : 0, - missing : 0 - } - }; - // Remake the objects into what the reporters expect - _.each(coverageData.files, function(fileData, fileName) { - var stats = fileData.stats; - fileData.filename = fileName; - fileData.stats = function() { return stats; }; - fileData.source = stats.source; - _.each(['missing', 'seen', 'total'], function(field) { - overall[field] += stats[field]; - overall.blocks[field] += stats.blocks[field]; - }); - }); - - overall.percentage = overall.seen / overall.total; - overall.blocks.percentage = overall.blocks.seen / overall.blocks.total; - coverageData.overall = { - filename: 'Overall', - stats: function() { return overall; } - }; - - return coverageData; - }; - - var loadPrecombinedCoverageData = function(configs) { - var dataDirectory = configs.dataDirectory; - var dataPrefix = configs.prefix; - - var filesInDataDirectory = fs.readdirSync(dataDirectory); - var files = _.filter(filesInDataDirectory, function(file) { - return _s.startsWith(file, "precombined_" + dataPrefix); - }).map(function(file) { - return path.join(dataDirectory, file); - }); - - - var datas = []; - _.each(files, function(filename) { - // If it doesn't exist, then error out - if (!exists(filename)) { - console.error("Coverage data file does not exist: " + filename); - process.exit(1); - } - - // Read the file - var data = fs.readFileSync(filename, "utf-8"); - datas.push(JSON.parse(data)); - - fs.unlinkSync(filename); - }); - - var coverageData = cover.load(datas); - return coverageData; - }; - - /* ====== Reporters ====== */ - - var reporterHandlers = { - html: function(coverageData, config) { - fileData = coverageData.files; - var files = _.sortBy(_.keys(fileData), function(file) { return file; }); - var allStats = []; - var statsByFile = {}; - - var htmlDirectory = path.join(CWD, config.html.directory); - var templateDir = path.resolve(__dirname, "..", "templates"); - var resourceDir = path.resolve(__dirname, "..", "resources"); - - function statsRow(name, stats) { - return [ - name, - Math.floor(stats.percentage * 100) + "%", - stats.missing, - stats.total, - Math.floor(stats.blocks.percentage * 100) + "%", - stats.blocks.missing, - stats.blocks.total - ]; - } - - var htmls = {}; - for(var i = 0; i < files.length; i++) { - var filename = files[i]; - htmls[filename] = cover.reporters.html.format(fileData[filename]); - } - - // For each file, we compile a list of its summmary stats - for(var i = 0; i < files.length; i++) { - var filename = files[i]; - var stats = fileData[filename].stats(); - - statsByFile[filename] = { - percentage: Math.floor(stats.percentage * 100) + "%", - missingLines: stats.missing, - seenLines: stats.seen, - partialLines: _.values(stats.coverage).filter(function(lineinfo) { return lineinfo.partial; }).length, - totalLines: stats.total, - blockPercentage: Math.floor(stats.blocks.percentage * 100) + "%", - missingBlocks: stats.blocks.missing, - seenBlocks: stats.blocks.seen, - totalBlocks: stats.blocks.total, - }; - - allStats.push(statsRow(path.relative(CWD, filename), stats)); - } - - allStats.push(statsRow('Overall', coverageData.overall.stats())); - - // Delete the HTML directory if necessary, and then create it - if (exists(htmlDirectory)) { - rmdirRecursiveSync(htmlDirectory); - } - fs.mkdirSync(htmlDirectory, "755"); - - // For each HTML file, use the template to generate an HTML file, - // and write it out to disk - _.each(htmls, function(html, filename) { - var outputPath = path.join(htmlDirectory, filename.replace(/[\/|\:|\\]/g, "_") + ".html"); - - var htmlTemplateString = fs.readFileSync(path.join(templateDir, "file.html")).toString("utf-8"); - var htmlTemplate = _.template(htmlTemplateString); - var completeHtml = htmlTemplate({ - filename: filename, - code: html, - stats: statsByFile[filename] - }); - - fs.writeFileSync(outputPath, completeHtml); - }); - - // Compile the index file with the template, and write it out to disk - var indexTemplateString = fs.readFileSync(path.join(templateDir, "index.html")).toString("utf-8"); - var indexTemplate = _.template(indexTemplateString); - var headers = ["Filename", "% Covered", "Missed Lines", "# Lines", "% Blocks", "Missed Blocks", "# Blocks"]; - var fileUrls = {}; - _.each(files, function(file) { - fileUrls[path.relative(CWD, file)] = file.replace(/[\/|\:|\\]/g, "_") + ".html"; - }); - - var indexHtml = indexTemplate({ headers: headers, data: allStats, fileUrls: fileUrls }); - - fs.writeFileSync(path.join(htmlDirectory, "index.html"), indexHtml); - - // Copy over the resource files - fs.link(path.join(resourceDir, "bootstrap.css"), path.join(htmlDirectory, "bootstrap.css")); - fs.link(path.join(resourceDir, "prettify.css"), path.join(htmlDirectory, "prettify.css")); - fs.link(path.join(resourceDir, "prettify.js"), path.join(htmlDirectory, "prettify.js")); - fs.link(path.join(resourceDir, "jquery.min.js"), path.join(htmlDirectory, "jquery.min.js")); - fs.link(path.join(resourceDir, "jquery.tablesorter.min.js"), path.join(htmlDirectory, "jquery.tablesorter.min.js")); - }, - - cli: function(coverageData, config) { - fileData = coverageData.files; - var files = _.sortBy(_.keys(fileData), function(file) { return file; }); - - var table = new Table({ - head: ["Filename", "% Covered", "Missed Lines", "# Lines", "% Blocks", "Missed Blocks", "# Blocks"], - style : { - 'padding-left' : 1, - 'padding-right ': 1, - head: ['cyan'] - }, - colWidths: [cover.reporters.cli.MAX_FILENAME_LENGTH + 5, 10, 14, 10, 10, 14, 10] - }); - - for(var i = 0; i < files.length; i++) { - var filename = files[i]; - table.push(cover.reporters.cli.format(fileData[filename])); - } - - table.push(cover.reporters.cli.format(coverageData.overall)); - - console.log(table.toString()); - }, - - plain: function(coverageData, config) { - fileData = coverageData.files; - var files = _.sortBy(_.keys(fileData), function(file) { return file; }); - - for(var i = 0; i < files.length; i++) { - var filename = files[i]; - console.log(cover.reporters.plain.format(fileData[filename])); - } - }, - - json: function(coverageData, config) { - fileData = coverageData.files; - var files = _.sortBy(_.keys(fileData), function(file) { return file; }); - - var jsons = []; - for(var i = 0; i < files.length; i++) { - var filename = files[i]; - jsons.push(cover.reporters.json.format(fileData[filename])); - } - - jsons.push(cover.reporters.json.format(coverageData.overall)); - - console.log(JSON.stringify(jsons)); - }, - - __catch_all: function(coverageData, config, reporter) { - - } - }; - - /* ====== Commands ====== */ - - var run = function(file, cmdline, config, ignore, debug) { - if (debug) { - var debugDirectory = path.join(CWD, config.debugDirectory); - if (!exists(debugDirectory)) { - fs.mkdirSync(debugDirectory, "0755"); - } - } - - // Run the file - var coverage = runFile(file, cmdline, ignore, debug ? config.debugDirectory : null); - - // Setup the on exit listener - process.on( - "exit", - function() { - // For debugging purposes, make sure we can print things - patch_console.patch(); - - if (!coverage) { - return; - } - - coverage(function(coverageData) { - try { - saveCoverageData(coverageData, config); - } - catch(e) { - console.log(e.stack); - } - }); - } - ); - }; - - var report = function(reporterName, file, config, ignore) { - var coverageData = loadCoverageData(file, config); - - reporterName = reporterName || "cli"; - - var reporter = ""; - if (cover.reporters[reporterName]) { - reporter = cover.reporters[reporterName]; - } - else { - try { - reporter = require(path.resolve(reporterName)); - } - catch(ex) { - console.log("Could not find reporter: " + reporterName); - process.exit(1); - } - } - - (reporterHandlers[reporterName] || reporterHandlers.__catch_all)(coverageData, config, reporter); - } - - var combine = function(configFile, ignoreFile) { - var files = getOptionsAndIgnore({config: configFile, ignore: ignoreFile}); - var config = files.config; - var ignore = files.ignore; - - var coverageData = loadPrecombinedCoverageData(config); - saveCoverageData(coverageData, config, true); - } - - var hook = function(configFile, ignoreFile) { - var files = getOptionsAndIgnore({config: configFile, ignore: ignoreFile}); - var config = files.config; - var ignore = files.ignore; - - var cover = require('../index.js'); - coverage = cover.cover(null, ignore, global); - - // Setup the on exit listener - process.on( - "exit", - function() { - // For debugging purposes, make sure we can print things - patch_console.patch(); - coverage(function(coverageData) { - try { - saveCoverageData(coverageData, config); - } - catch(e) { - console.log(e.stack); - } - }); - } - ); - } - - var hookAndReport = function(reporterName, configFile, ignoreFile) { - var files = getOptionsAndIgnore({config: configFile, ignore: ignoreFile}); - var config = files.config; - var ignore = files.ignore; - - hook(configFile, ignoreFile); - process.on("exit", function() { - report(reporterName, null, config, ignore); - }); - } - - var hookAndCombine = function(configFile, ignoreFile) { - var files = getOptionsAndIgnore({config: configFile, ignore: ignoreFile}); - var config = files.config; - var ignore = files.ignore; - - hook(configFile, ignoreFile); - process.on("exit", function() { - combine(config); - }); - } - - var hookAndCombineAndReport = function(reporterName, configFile, ignoreFile) { - var files = getOptionsAndIgnore({config: configFile, ignore: ignoreFile}); - var config = files.config; - var ignore = files.ignore; - - hook(configFile, ignoreFile); - process.on("exit", function() { - combine(config); - report(reporterName, null, config, ignore); - }); - } - - /* ====== Command Line Parsing ====== */ - - commander - .version(pkg.version) - .option("-c, --config ", "Path to a .coverrc file") - .option("-i, --ignore ", "Path to a .coverignore file") - - commander.command("run ") - .description("Run a file and collect code coverage information for it") - .option("-d, --debug", "Enable debugging") - .option("-m, --modules", "Enable coverage for node_modules") - .action(function(file, options) { - var configs = getOptionsAndIgnore(this, options); - var config = configs.config; - var ignore = configs.ignore; - var debug = options.debug; - - // Remove the command itself - var cmdline = this.args.slice(1); - - run(file, cmdline, config, ignore, debug); - }); - - commander.command("report [reporter] [file]") - .description("Report on saved coverage data. Specify a coverage file and a reporter: " + reporterOptions) - .action(function(reporterName, file) { - var configs = getOptionsAndIgnore(this); - var config = configs.config; - var ignore = configs.ignore; - - report(reporterName, file, config, ignore); - }); - - commander.command("combine") - .description("Combine multiple coverage files (from multiple runs) into a single, reportable file") - .action(function(reporterName, file) { - var configs = getOptionsAndIgnore(this); - var config = configs.config; - var ignore = configs.ignore; - - combine(config, ignore); - }); - - var printHelp = function() { - console.log(commander.helpInformation()); - } - - commander.command("*") - .action(function() { - printHelp(); - }); - - /* ====== Exports ====== */ - - module.exports = { - parse: function(argv) { - var cmdline = commander.parse(argv); - if (!cmdline.executedCommand) { - printHelp(); - } - - return cmdline; - }, - run: run, - report: report, - hook: hook, - hookAndReport: hookAndReport, - combine: combine, - hookAndCombine: hookAndCombine, - hookAndCombineAndReport: hookAndCombineAndReport - }; -})(); - -if (module === require.main) { - module.exports.parse(process.argv); -} diff --git a/contrib/cli-table/README.md b/contrib/cli-table/README.md deleted file mode 100644 index ea1e0ef..0000000 --- a/contrib/cli-table/README.md +++ /dev/null @@ -1,77 +0,0 @@ - -CLI Table -========= - -This utility allows you to render unicode-aided tables on the command line from -your node.js scripts. - -![Screenshot](http://cl.ly/3qxy/Screen_shot_2011-01-03_at_6.56.32_PM.png) - -## Features - -- Customizable characters that constitute the table. -- Color/background styling in the header through - [colors.js](http://github.com/marak/colors.js) -- Column width customization -- Text truncation based on predefined widths -- Text alignment (left, right, center) -- Padding (left, right) -- Easy-to-use API - -## Installation - - npm install cli-table - -## How to use - - var Table = require('cli-table'); - - // instantiate - var table = new Table({ - head: ['TH 1 label', 'TH 2 label'] - , colWidths: [100, 200] - }); - - // table is an Array, so you can `push`, `unshift`, `splice` and friends - table.push( - ['First value', 'Second value'] - , ['First value', 'Second value'] - ); - - // render - console.log(table.toString()); - -## Running tests - -Clone the repository with all its submodules and run: - - $ make test - -## Credits - -- Guillermo Rauch <guillermo@learnboost.com> ([Guille](http://github.com/guille)) - -## License - -(The MIT License) - -Copyright (c) 2010 LearnBoost <dev@learnboost.com> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contrib/cli-table/index.js b/contrib/cli-table/index.js deleted file mode 100644 index 1c01669..0000000 --- a/contrib/cli-table/index.js +++ /dev/null @@ -1,2 +0,0 @@ - -module.exports = require('./lib/cli-table'); diff --git a/contrib/cli-table/lib/cli-table/index.js b/contrib/cli-table/lib/cli-table/index.js deleted file mode 100644 index 60992c1..0000000 --- a/contrib/cli-table/lib/cli-table/index.js +++ /dev/null @@ -1,205 +0,0 @@ - -/** - * Module dependencies. - */ - -var utils = require('./utils') - , repeat = utils.repeat - , truncate = utils.truncate - , pad = utils.pad; - -require('../../../colors'); - -/** - * Table constructor - * - * @param {Object} options - * @api public - */ - -function Table (options){ - this.options = utils.options({ - chars: { - 'top': '━' - , 'top-mid': '┳' - , 'top-left': '┏' - , 'top-right': '┓' - , 'bottom': '━' - , 'bottom-mid': '┻' - , 'bottom-left': '┗' - , 'bottom-right': '┛' - , 'left': '┃' - , 'left-mid': '┣' - , 'mid': '━' - , 'mid-mid': '╋' - , 'right': '┃' - , 'right-mid': '┫' - } - , truncate: '…' - , colWidths: [] - , colAligns: [] - , style: { - 'padding-left': 1 - , 'padding-right': 1 - , head: ['cyan'] - } - , head: [] - }, options); -}; - -/** - * Inherit from Array. - */ - -Table.prototype.__proto__ = Array.prototype; - -/** - * Width getter - * - * @return {Number} width - * @api public - */ - -Table.prototype.__defineGetter__('width', function (){ - var str = this.toString().split("\n"); - if (str.length) return str[0].length; - return 0; -}); - -/** - * Render to a string. - * - * @return {String} table representation - * @api public - */ - -Table.prototype.render -Table.prototype.toString = function (){ - var ret = '' - , options = this.options - , style = options.style - , head = options.head - , chars = options.chars - , truncater = options.truncate - , colWidths = options.colWidths || new Array(this.head.length) - , totalWidth = 0; - - if (!head.length && !this.length) return ''; - - if (!colWidths.length){ - this.slice(0).concat([head]).forEach(function(cells){ - cells.forEach(function(cell, i){ - var width = typeof cell == 'object' && cell.width != undefined - ? cell.width - : ((typeof cell == 'object' ? utils.strlen(cell.text) : utils.strlen(cell)) + (style['padding-left'] || 0) + (style['padding-right'] || 0)) - colWidths[i] = Math.max(colWidths[i] || 0, width || 0); - }); - }); - }; - - totalWidth = (colWidths.length == 1 ? colWidths[0] : colWidths.reduce( - function (a, b){ - return a + b - })) + colWidths.length + 1; - - // draws a line - function line (line, left, right, intersection){ - var width = 0 - , line = - left - + repeat(line, totalWidth - 2) - + right; - - colWidths.forEach(function (w, i){ - if (i == colWidths.length - 1) return; - width += w + 1; - line = line.substr(0, width) + intersection + line.substr(width + 1); - }); - - ret += line; - }; - - // draws the top line - function lineTop (){ - line(chars.top - , chars['top-left'] || chars.top - , chars['top-right'] || chars.top - , chars['top-mid']); - ret += "\n"; - }; - - // renders a string, by padding it or truncating it - function string (str, index){ - var str = String(typeof str == 'object' && str.text ? str.text : str) - , length = utils.strlen(str) - , width = colWidths[index] - - (style['padding-left'] || 0) - - (style['padding-right'] || 0) - , align = options.colAligns[index] || 'left'; - - return repeat(' ', style['padding-left'] || 0) - + (length == width ? str : - (length < width - ? pad(str, ( width + (str.length - length) ), ' ', align == 'left' ? 'right' : - (align == 'middle' ? 'both' : 'left')) - : (truncater ? truncate(str, width, truncater) : str)) - ) - + repeat(' ', style['padding-right'] || 0); - }; - - if (head.length){ - lineTop(); - - ret += chars.left; - - head.forEach(function (th, index){ - var text = string(th, index); - if (style.head){ - style.head.forEach(function(style){ - text = text[style]; - }); - } - - ret += text; - ret += chars.right; - }); - - ret += "\n"; - } - - if (this.length) - this.forEach(function (cells, i){ - if (!head.length && i == 0) - lineTop(); - else { - line(chars.mid - , chars['left-mid'] - , chars['right-mid'] - , chars['mid-mid']); - - ret += "\n" + chars.left; - - cells.forEach(function(cell, i){ - ret += string(cell, i); - ret += chars.right; - }); - - ret += "\n"; - } - }); - - line(chars.bottom - , chars['bottom-left'] || chars.bottom - , chars['bottom-right'] || chars.bottom - , chars['bottom-mid']); - - return ret; -}; - -/** - * Module exports. - */ - -module.exports = Table; - -module.exports.version = '0.0.1'; \ No newline at end of file diff --git a/contrib/cli-table/lib/cli-table/utils.js b/contrib/cli-table/lib/cli-table/utils.js deleted file mode 100644 index 892a93c..0000000 --- a/contrib/cli-table/lib/cli-table/utils.js +++ /dev/null @@ -1,95 +0,0 @@ - -/** - * Repeats a string. - * - * @param {String} char(s) - * @param {Number} number of times - * @return {String} repeated string - */ - -exports.repeat = function (str, times){ - return Array(times + 1).join(str); -}; - -/** - * Pads a string - * - * @api public - */ - -exports.pad = function (str, len, pad, dir) { - if (len + 1 >= str.length) - switch (dir){ - case 'left': - str = Array(len + 1 - str.length).join(pad) + str; - break; - - case 'both': - var right = Math.ceil((padlen = len - str.length) / 2); - var left = padlen - right; - str = Array(left + 1).join(pad) + str + Array(right + 1).join(pad); - break; - - default: - str = str + Array(len + 1 - str.length).join(pad); - }; - - return str; -}; - -/** - * Truncates a string - * - * @api public - */ - -exports.truncate = function (str, length, chr){ - chr = chr || '…'; - return str.length >= length ? str.substr(0, length - chr.length) + chr : str; -}; - -/** - * Copies and merges options with defaults. - * - * @param {Object} defaults - * @param {Object} supplied options - * @return {Object} new (merged) object - */ - -function clone(a){ - var b; - if (Array.isArray(a)){ - b = []; - for (var i = 0, l = a.length; i < l; i++) - b.push(typeof a[i] == 'object' ? clone(a[i]) : a[i]); - return b; - } else if (typeof a == 'object'){ - b = {}; - for (var i in a) - b[i] = typeof a[i] == 'object' ? clone(a[i]) : a[i]; - return b; - } - return a; -}; - -exports.options = function (defaults, opts){ - var c = clone(opts); - for (var i in defaults) - if (!(i in opts)) - c[i] = defaults[i]; - return c; -}; - - -// -// For consideration of terminal "color" programs like colors.js, -// which can add ANSI escape color codes to strings, -// we destyle the ANSI color escape codes for padding calculations. -// -// see: http://en.wikipedia.org/wiki/ANSI_escape_code -// -exports.strlen = function(str){ - var code = /\u001b\[\d+m/g; - var stripped = ("" + str).replace(code,''); - return stripped.length; -} \ No newline at end of file diff --git a/contrib/colors.js b/contrib/colors.js deleted file mode 100644 index b981317..0000000 --- a/contrib/colors.js +++ /dev/null @@ -1,304 +0,0 @@ -/* -colors.js - -Copyright (c) 2010 - -Marak Squires -Alexis Sellier (cloudhead) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var isHeadless = false; - -if (typeof module !== 'undefined') { - isHeadless = true; -} - -if (!isHeadless) { - var exports = {}; - var module = {}; - var colors = exports; - exports.mode = "browser"; -} else { - exports.mode = "console"; -} - -// -// Prototypes the string object to have additional method calls that add terminal colors -// -var addProperty = function (color, func) { - exports[color] = function (str) { - return func.apply(str); - }; - String.prototype.__defineGetter__(color, func); -}; - - - -function stylize(str, style) { - - var styles; - - if (exports.mode === 'console') { - styles = { - //styles - 'bold' : ['\033[1m', '\033[22m'], - 'italic' : ['\033[3m', '\033[23m'], - 'underline' : ['\033[4m', '\033[24m'], - 'inverse' : ['\033[7m', '\033[27m'], - //grayscale - 'white' : ['\033[37m', '\033[39m'], - 'grey' : ['\033[90m', '\033[39m'], - 'black' : ['\033[30m', '\033[39m'], - //colors - 'blue' : ['\033[34m', '\033[39m'], - 'cyan' : ['\033[36m', '\033[39m'], - 'green' : ['\033[32m', '\033[39m'], - 'magenta' : ['\033[35m', '\033[39m'], - 'red' : ['\033[31m', '\033[39m'], - 'yellow' : ['\033[33m', '\033[39m'] - }; - } else if (exports.mode === 'browser') { - styles = { - //styles - 'bold' : ['', ''], - 'italic' : ['', ''], - 'underline' : ['', ''], - 'inverse' : ['', ''], - //grayscale - 'white' : ['', ''], - 'grey' : ['', ''], - 'black' : ['', ''], - //colors - 'blue' : ['', ''], - 'cyan' : ['', ''], - 'green' : ['', ''], - 'magenta' : ['', ''], - 'red' : ['', ''], - 'yellow' : ['', ''] - }; - } else if (exports.mode === 'none') { - return str; - } else { - console.log('unsupported mode, try "browser", "console" or "none"'); - } - return styles[style][0] + str + styles[style][1]; -} - -function applyTheme(theme) { - - // - // Remark: This is a list of methods that exist - // on String that you should not overwrite. - // - var stringPrototypeBlacklist = [ - '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', - 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', - 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', - 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' - ]; - - Object.keys(theme).forEach(function (prop) { - if (stringPrototypeBlacklist.indexOf(prop) !== -1) { - console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); - } else { - addProperty(prop, function () { - return exports[theme[prop]](this); - }); - } - }); -} - - -// -// Iterate through all default styles and colors -// -var x = ['bold', 'underline', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; -x.forEach(function (style) { - - // __defineGetter__ at the least works in more browsers - // http://robertnyman.com/javascript/javascript-getters-setters.html - // Object.defineProperty only works in Chrome - addProperty(style, function () { - return stylize(this, style); - }); -}); - -function sequencer(map) { - return function () { - if (!isHeadless) { - return this.replace(/( )/, '$1'); - } - var exploded = this.split(""), i = 0; - exploded = exploded.map(map); - return exploded.join(""); - }; -} - -var rainbowMap = (function () { - var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV - return function (letter, i, exploded) { - if (letter === " ") { - return letter; - } else { - return stylize(letter, rainbowColors[i++ % rainbowColors.length]); - } - }; -})(); - -exports.themes = {}; - -exports.addSequencer = function (name, map) { - addProperty(name, sequencer(map)); -}; - -exports.addSequencer('rainbow', rainbowMap); -exports.addSequencer('zebra', function (letter, i, exploded) { - return i % 2 === 0 ? letter : letter.inverse; -}); - -exports.setTheme = function (theme) { - if (typeof theme === 'string') { - try { - exports.themes[theme] = require(theme); - applyTheme(exports.themes[theme]); - return exports.themes[theme]; - } catch (err) { - console.log(err); - return err; - } - } else { - applyTheme(theme); - } -}; - - -addProperty('stripColors', function () { - return ("" + this).replace(/\u001b\[\d+m/g, ''); -}); - -// please no -function zalgo(text, options) { - var soul = { - "up" : [ - '̍', '̎', '̄', '̅', - '̿', '̑', '̆', '̐', - '͒', '͗', '͑', '̇', - '̈', '̊', '͂', '̓', - '̈', '͊', '͋', '͌', - '̃', '̂', '̌', '͐', - '̀', '́', '̋', '̏', - '̒', '̓', '̔', '̽', - '̉', 'ͣ', 'ͤ', 'ͥ', - 'ͦ', 'ͧ', 'ͨ', 'ͩ', - 'ͪ', 'ͫ', 'ͬ', 'ͭ', - 'ͮ', 'ͯ', '̾', '͛', - '͆', '̚' - ], - "down" : [ - '̖', '̗', '̘', '̙', - '̜', '̝', '̞', '̟', - '̠', '̤', '̥', '̦', - '̩', '̪', '̫', '̬', - '̭', '̮', '̯', '̰', - '̱', '̲', '̳', '̹', - '̺', '̻', '̼', 'ͅ', - '͇', '͈', '͉', '͍', - '͎', '͓', '͔', '͕', - '͖', '͙', '͚', '̣' - ], - "mid" : [ - '̕', '̛', '̀', '́', - '͘', '̡', '̢', '̧', - '̨', '̴', '̵', '̶', - '͜', '͝', '͞', - '͟', '͠', '͢', '̸', - '̷', '͡', ' ҉' - ] - }, - all = [].concat(soul.up, soul.down, soul.mid), - zalgo = {}; - - function randomNumber(range) { - var r = Math.floor(Math.random() * range); - return r; - } - - function is_char(character) { - var bool = false; - all.filter(function (i) { - bool = (i === character); - }); - return bool; - } - - function heComes(text, options) { - var result = '', counts, l; - options = options || {}; - options["up"] = options["up"] || true; - options["mid"] = options["mid"] || true; - options["down"] = options["down"] || true; - options["size"] = options["size"] || "maxi"; - text = text.split(''); - for (l in text) { - if (is_char(l)) { - continue; - } - result = result + text[l]; - counts = {"up" : 0, "down" : 0, "mid" : 0}; - switch (options.size) { - case 'mini': - counts.up = randomNumber(8); - counts.min = randomNumber(2); - counts.down = randomNumber(8); - break; - case 'maxi': - counts.up = randomNumber(16) + 3; - counts.min = randomNumber(4) + 1; - counts.down = randomNumber(64) + 3; - break; - default: - counts.up = randomNumber(8) + 1; - counts.mid = randomNumber(6) / 2; - counts.down = randomNumber(8) + 1; - break; - } - - var arr = ["up", "mid", "down"]; - for (var d in arr) { - var index = arr[d]; - for (var i = 0 ; i <= counts[index]; i++) { - if (options[index]) { - result = result + soul[index][randomNumber(soul[index].length)]; - } - } - } - } - return result; - } - return heComes(text); -} - - -// don't summon zalgo -addProperty('zalgo', function () { - return zalgo(this); -}); \ No newline at end of file diff --git a/contrib/commander.js b/contrib/commander.js deleted file mode 100644 index 1a00e97..0000000 --- a/contrib/commander.js +++ /dev/null @@ -1,1108 +0,0 @@ - -/*! - * commander - * Copyright(c) 2011 TJ Holowaychuk - * MIT Licensed - */ - -/*! - * Console - */ -var util = require('util'); -var fs = require("fs"); - -/* Monkey patching */ -if (!util.format) { - var formatRegExp = /%[sdj%]/g; - util.format = function(f) { - if (typeof f !== 'string') { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(util.inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': return JSON.stringify(args[i++]); - case '%%': return '%'; - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (x === null || typeof x !== 'object') { - str += ' ' + x; - } else { - str += ' ' + util.inspect(x); - } - } - return str; - } -} - -var consoleFlush = function(data) { - if (!Buffer.isBuffer(data)) { - data= new Buffer(''+ data); - } - if (data.length) { - var written= 0; - do { - try { - var len = data.length- written; - written += fs.writeSync(process.stdout.fd, data, written, len, -1); - } - catch (e) { - } - } while(written < data.length); - } -}; - -/** - * Module dependencies. - */ - -var EventEmitter = require('events').EventEmitter - , path = require('path') - , tty = require('tty') - , basename = path.basename; - -/** - * Expose the root command. - */ - -exports = module.exports = new Command; - -/** - * Expose `Command`. - */ - -exports.Command = Command; - -/** - * Expose `Option`. - */ - -exports.Option = Option; - -/** - * Initialize a new `Option` with the given `flags` and `description`. - * - * @param {String} flags - * @param {String} description - * @api public - */ - -function Option(flags, description) { - this.flags = flags; - this.required = ~flags.indexOf('<'); - this.optional = ~flags.indexOf('['); - this.bool = !~flags.indexOf('-no-'); - flags = flags.split(/[ ,|]+/); - if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); - this.long = flags.shift(); - this.description = description; -} - -/** - * Return option name. - * - * @return {String} - * @api private - */ - -Option.prototype.name = function(){ - return this.long - .replace('--', '') - .replace('no-', ''); -}; - -/** - * Check if `arg` matches the short or long flag. - * - * @param {String} arg - * @return {Boolean} - * @api private - */ - -Option.prototype.is = function(arg){ - return arg == this.short - || arg == this.long; -}; - -/** - * Initialize a new `Command`. - * - * @param {String} name - * @api public - */ - -function Command(name) { - this.commands = []; - this.options = []; - this.args = []; - this.name = name; - this.opts = {}; -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -Command.prototype.__proto__ = EventEmitter.prototype; - -/** - * Add command `name`. - * - * The `.action()` callback is invoked when the - * command `name` is specified via __ARGV__, - * and the remaining arguments are applied to the - * function for access. - * - * When the `name` is "*" an un-matched command - * will be passed as the first arg, followed by - * the rest of __ARGV__ remaining. - * - * Examples: - * - * program - * .version('0.0.1') - * .option('-C, --chdir ', 'change the working directory') - * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') - * .option('-T, --no-tests', 'ignore test hook') - * - * program - * .command('setup') - * .description('run remote setup commands') - * .action(function(){ - * console.log('setup'); - * }); - * - * program - * .command('exec ') - * .description('run the given remote command') - * .action(function(cmd){ - * console.log('exec "%s"', cmd); - * }); - * - * program - * .command('*') - * .description('deploy the given env') - * .action(function(env){ - * console.log('deploying "%s"', env); - * }); - * - * program.parse(process.argv); - * - * @param {String} name - * @return {Command} the new command - * @api public - */ - -Command.prototype.command = function(name){ - var args = name.split(/ +/); - var cmd = new Command(args.shift()); - this.commands.push(cmd); - cmd.parseExpectedArgs(args); - cmd.parent = this; - return cmd; -}; - -/** - * Parse expected `args`. - * - * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. - * - * @param {Array} args - * @return {Command} for chaining - * @api public - */ - -Command.prototype.parseExpectedArgs = function(args){ - if (!args.length) return; - var self = this; - args.forEach(function(arg){ - switch (arg[0]) { - case '<': - self.args.push({ required: true, name: arg.slice(1, -1) }); - break; - case '[': - self.args.push({ required: false, name: arg.slice(1, -1) }); - break; - } - }); - return this; -}; - -/** - * Register callback `fn` for the command. - * - * Examples: - * - * program - * .command('help') - * .description('display verbose help') - * .action(function(){ - * // output help here - * }); - * - * @param {Function} fn - * @return {Command} for chaining - * @api public - */ - -Command.prototype.action = function(fn){ - var self = this; - this.parent.on(this.name, function(args, unknown){ - - args = args.slice(); - // Parse any so-far unknown options - unknown = unknown || []; - var parsed = self.parseOptions(unknown); - - // Output help if necessary - outputHelpIfNecessary(self, parsed.unknown); - - // If there are still any unknown options, then we simply - // die, unless someone asked for help, in which case we give it - // to them, and then we die. - if (parsed.unknown.length > 0) { - self.unknownOption(parsed.unknown[0]); - } - - // If we were expecting a required option and we missed it, - // error out - self.options.forEach(function(option, i) { - var oname = option.name(); - var name = camelcase(oname); - if (option.isPresenceRequired && self[name] === undefined && !parsed.required[oname]) { - self.optionMissing(option); - } - }); - - self.args.forEach(function(arg, i){ - if (arg.required && null == args[i]) { - self.missingArgument(arg.name); - } - }); - - // Always append ourselves to the end of the arguments, - // to make sure we match the number of arguments the user - // expects - // If we have expected arguments and we have at most the number of - // expected arguments, then add it to the end. If not, push us - // at the end (for the case of varargs). - if (self.args.length && (args.length <= self.args.length - 1)) { - args[self.args.length] = self; - } else { - args.push(self); - } - - fn.apply(this, args); - }); - return this; -}; - -/** - * Define option with `flags`, `description` and optional - * coercion `fn`. - * - * The `flags` string should contain both the short and long flags, - * separated by comma, a pipe or space. The following are all valid - * all will output this way when `--help` is used. - * - * "-p, --pepper" - * "-p|--pepper" - * "-p --pepper" - * - * Examples: - * - * // simple boolean defaulting to false - * program.option('-p, --pepper', 'add pepper'); - * - * --pepper - * program.pepper - * // => Boolean - * - * // simple boolean defaulting to false - * program.option('-C, --no-cheese', 'remove cheese'); - * - * program.cheese - * // => true - * - * --no-cheese - * program.cheese - * // => true - * - * // required argument - * program.option('-C, --chdir ', 'change the working directory'); - * - * --chdir /tmp - * program.chdir - * // => "/tmp" - * - * // optional argument - * program.option('-c, --cheese [type]', 'add cheese [marble]'); - * - * @param {String} flags - * @param {String} description - * @param {Function|Mixed} fn or default - * @param {Mixed} defaultValue - * @return {Command} for chaining - * @api public - */ - -Command.prototype.option = function(flags, description, fn, defaultValue, isRequired){ - var self = this - , option = new Option(flags, description) - , oname = option.name() - , name = camelcase(oname); - - // default as 3rd arg - if ('function' != typeof fn) isRequired = defaultValue, defaultValue = fn, fn = null; - - // preassign default value only for --no-*, [optional], or - if (false == option.bool || option.optional || option.required) { - // when --no-* we make sure default is true - if (false == option.bool) defaultValue = true; - // preassign only if we have a default - if (undefined !== defaultValue) self[name] = defaultValue; - } - - option.isPresenceRequired = isRequired; - - // register the option - this.options.push(option); - - // when it's passed assign the value - // and conditionally invoke the callback - this.on(oname, function(val){ - // coercion - if (null != val && fn) val = fn(val); - - // unassigned or bool - if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { - // if no value, bool true, and we have a default, then use it! - if (null == val) { - self[name] = self.opts[name] = option.bool - ? defaultValue || true - : false; - } else { - self[name] = self.opts[name] = val; - } - } else if (null !== val) { - // reassign - self[name] = self.opts[name] = val; - } - }); - - return this; -}; - -/** - * Parse `argv`, settings options and invoking commands when defined. - * - * @param {Array} argv - * @return {Command} for chaining - * @api public - */ - -Command.prototype.parse = function(argv){ - // store raw args - this.rawArgs = argv; - - // guess name - if (!this.name) this.name = basename(argv[1]); - - // process argv - var parsed = this.parseOptions(this.normalize(argv.slice(2))); - this.args = parsed.args; - return this.parseArgs(this.args, parsed.unknown, parsed.required); -}; - -/** - * Normalize `args`, splitting joined short flags. For example - * the arg "-abc" is equivalent to "-a -b -c". - * - * @param {Array} args - * @return {Array} - * @api private - */ - -Command.prototype.normalize = function(args){ - var ret = [] - , arg; - - for (var i = 0, len = args.length; i < len; ++i) { - arg = args[i]; - if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { - arg.slice(1).split('').forEach(function(c){ - ret.push('-' + c); - }); - } else { - ret.push(arg); - } - } - - return ret; -}; - -/** - * Parse command `args`. - * - * When listener(s) are available those - * callbacks are invoked, otherwise the "*" - * event is emitted and those actions are invoked. - * - * @param {Array} args - * @return {Command} for chaining - * @api private - */ - -Command.prototype.parseArgs = function(args, unknown, required){ - var cmds = this.commands - , len = cmds.length - , self = this - , name; - - if (args.length) { - name = args[0]; - if (this.listeners(name).length) { - var commandName = args.shift(); - this.executedCommand = commandName; - this.emit(commandName, args, unknown); - } else { - this.executedCommand = "*"; - this.emit('*', args); - } - } else { - outputHelpIfNecessary(this, unknown); - - // If there were no args and we have unknown options, - // then they are extraneous and we need to error. - if (unknown.length > 0) { - this.unknownOption(unknown[0]); - } - - // If we were expecting a required option and we missed it, - // error out - this.options.forEach(function(option, i) { - var oname = option.name(); - var name = camelcase(oname); - if (option.isPresenceRequired && self[name] === undefined && !required[oname]) { - self.optionMissing(option); - } - }); - } - - return this; -}; - -/** - * Return an option matching `arg` if any. - * - * @param {String} arg - * @return {Option} - * @api private - */ - -Command.prototype.optionFor = function(arg){ - for (var i = 0, len = this.options.length; i < len; ++i) { - if (this.options[i].is(arg)) { - return this.options[i]; - } - } -}; - -/** - * Parse options from `argv` returning `argv` - * void of these options. - * - * @param {Array} argv - * @return {Array} - * @api public - */ - -Command.prototype.parseOptions = function(argv){ - var args = [] - , len = argv.length - , literal - , option - , arg; - - var unknownOptions = []; - var required = {}; - - // parse options - for (var i = 0; i < len; ++i) { - arg = argv[i]; - - // literal args after -- - if ('--' == arg) { - literal = true; - continue; - } - - if (literal) { - args.push(arg); - continue; - } - - // find matching Option - option = this.optionFor(arg); - - // option is defined - if (option) { - if (option.isPresenceRequired) { - required[option.name()] = true; - } - - // requires arg - if (option.required) { - arg = argv[++i]; - if (null == arg) return this.optionMissingArgument(option); - if ('-' == arg[0]) return this.optionMissingArgument(option, arg); - this.emit(option.name(), arg); - // optional arg - } else if (option.optional) { - arg = argv[i+1]; - if (null == arg || '-' == arg[0]) { - arg = null; - } else { - ++i; - } - this.emit(option.name(), arg); - // bool - } else { - this.emit(option.name()); - } - continue; - } - - // looks like an option - if (arg.length > 1 && '-' == arg[0]) { - unknownOptions.push(arg); - - // If the next argument looks like it might be - // an argument for this option, we pass it on. - // If it isn't, then it'll simply be ignored - if (argv[i+1] && '-' != argv[i+1][0]) { - unknownOptions.push(argv[++i]); - } - continue; - } - - // arg - args.push(arg); - } - - return { args: args, unknown: unknownOptions, required: required }; -}; - -/** - * Argument `name` is missing. - * - * @param {String} name - * @api private - */ - -Command.prototype.missingArgument = function(name){ - console.error(); - console.error(" error: missing required argument `%s'", name); - console.error(); - process.exit(1); -}; - -/** - * `Option` is missing an argument, but received `flag` or nothing. - * - * @param {String} option - * @param {String} flag - * @api private - */ - -Command.prototype.optionMissingArgument = function(option, flag){ - console.error(); - if (flag) { - console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); - } else { - console.error(" error: option `%s' argument missing", option.flags); - } - console.error(); - process.exit(1); -}; - -/** - * `Option` is missing. - * - * @param {String} option - * @param {String} flag - * @api private - */ - -Command.prototype.optionMissing = function(option){ - console.error(); - console.error(" error: option `%s' is missing", option.name()); - console.error(); - process.exit(1); -}; - -/** - * Unknown option `flag`. - * - * @param {String} flag - * @api private - */ - -Command.prototype.unknownOption = function(flag){ - console.error(); - console.error(" error: unknown option `%s'", flag); - console.error(); - process.exit(1); -}; - -/** - * Set the program version to `str`. - * - * This method auto-registers the "-V, --version" flag - * which will print the version number when passed. - * - * @param {String} str - * @param {String} flags - * @return {Command} for chaining - * @api public - */ - -Command.prototype.version = function(str, flags){ - if (0 == arguments.length) return this._version; - this._version = str; - flags = flags || '-V, --version'; - this.option(flags, 'output the version number'); - this.on('version', function(){ - console.log(str); - process.exit(0); - }); - return this; -}; - -/** - * Set the description `str`. - * - * @param {String} str - * @return {String|Command} - * @api public - */ - -Command.prototype.description = function(str){ - if (0 == arguments.length) return this._description; - this._description = str; - return this; -}; - -/** - * Set / get the command usage `str`. - * - * @param {String} str - * @return {String|Command} - * @api public - */ - -Command.prototype.usage = function(str){ - var args = this.args.map(function(arg){ - return arg.required - ? '<' + arg.name + '>' - : '[' + arg.name + ']'; - }); - - var usage = '[options' - + (this.commands.length ? '] [command' : '') - + ']' - + (this.args.length ? ' ' + args : ''); - if (0 == arguments.length) return this._usage || usage; - this._usage = str; - - return this; -}; - -/** - * Return the largest option length. - * - * @return {Number} - * @api private - */ - -Command.prototype.largestOptionLength = function(){ - return this.options.reduce(function(max, option){ - return Math.max(max, option.flags.length); - }, 0); -}; - -/** - * Return help for options. - * - * @return {String} - * @api private - */ - -Command.prototype.optionHelp = function(){ - var width = this.largestOptionLength(); - - // Prepend the help information - return [pad('-h, --help', width) + ' ' + 'output usage information'] - .concat(this.options.map(function(option){ - return pad(option.flags, width) - + ' ' + option.description; - })) - .join('\n'); -}; - -/** - * Return command help documentation. - * - * @return {String} - * @api private - */ - -Command.prototype.commandHelp = function(){ - if (!this.commands.length) return ''; - return [ - '' - , ' Commands:' - , '' - , this.commands.map(function(cmd){ - var args = cmd.args.map(function(arg){ - return arg.required - ? '<' + arg.name + '>' - : '[' + arg.name + ']'; - }).join(' '); - - return cmd.name - + (cmd.options.length - ? ' [options]' - : '') + ' ' + args - + (cmd.description() - ? '\n' + cmd.description() - : ''); - }).join('\n\n').replace(/^/gm, ' ') - , '' - ].join('\n'); -}; - -/** - * Return program help documentation. - * - * @return {String} - * @api private - */ - -Command.prototype.helpInformation = function(){ - return [ - '' - , ' Usage: ' + this.name + ' ' + this.usage() - , '' + this.commandHelp() - , ' Options:' - , '' - , '' + this.optionHelp().replace(/^/gm, ' ') - , '' - , '' - ].join('\n'); -}; - -/** - * Prompt for a `Number`. - * - * @param {String} str - * @param {Function} fn - * @api private - */ - -Command.prototype.promptForNumber = function(str, fn){ - var self = this; - this.promptSingleLine(str, function parseNumber(val){ - val = Number(val); - if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); - fn(val); - }); -}; - -/** - * Prompt for a `Date`. - * - * @param {String} str - * @param {Function} fn - * @api private - */ - -Command.prototype.promptForDate = function(str, fn){ - var self = this; - this.promptSingleLine(str, function parseDate(val){ - val = new Date(val); - if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); - fn(val); - }); -}; - -/** - * Single-line prompt. - * - * @param {String} str - * @param {Function} fn - * @api private - */ - -Command.prototype.promptSingleLine = function(str, fn){ - if ('function' == typeof arguments[2]) { - return this['promptFor' + (fn.name || fn)](str, arguments[2]); - } - - process.stdout.write(str); - process.stdin.setEncoding('utf8'); - process.stdin.once('data', function(val){ - fn(val.trim()); - }).resume(); -}; - -/** - * Multi-line prompt. - * - * @param {String} str - * @param {Function} fn - * @api private - */ - -Command.prototype.promptMultiLine = function(str, fn){ - var buf = []; - console.log(str); - process.stdin.setEncoding('utf8'); - process.stdin.on('data', function(val){ - if ('\n' == val || '\r\n' == val) { - process.stdin.removeAllListeners('data'); - fn(buf.join('\n')); - } else { - buf.push(val.trimRight()); - } - }).resume(); -}; - -/** - * Prompt `str` and callback `fn(val)` - * - * Commander supports single-line and multi-line prompts. - * To issue a single-line prompt simply add white-space - * to the end of `str`, something like "name: ", whereas - * for a multi-line prompt omit this "description:". - * - * - * Examples: - * - * program.prompt('Username: ', function(name){ - * console.log('hi %s', name); - * }); - * - * program.prompt('Description:', function(desc){ - * console.log('description was "%s"', desc.trim()); - * }); - * - * @param {String} str - * @param {Function} fn - * @api public - */ - -Command.prototype.prompt = function(str, fn){ - if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); - this.promptMultiLine(str, fn); -}; - -/** - * Prompt for password with `str`, `mask` char and callback `fn(val)`. - * - * The mask string defaults to '', aka no output is - * written while typing, you may want to use "*" etc. - * - * Examples: - * - * program.password('Password: ', function(pass){ - * console.log('got "%s"', pass); - * process.stdin.destroy(); - * }); - * - * program.password('Password: ', '*', function(pass){ - * console.log('got "%s"', pass); - * process.stdin.destroy(); - * }); - * - * @param {String} str - * @param {String} mask - * @param {Function} fn - * @api public - */ - -Command.prototype.password = function(str, mask, fn){ - var self = this - , buf = ''; - - // default mask - if ('function' == typeof mask) { - fn = mask; - mask = ''; - } - - tty.setRawMode(true); - process.stdout.write(str); - - // keypress - process.stdin.on('keypress', function(c, key){ - if (key && 'enter' == key.name) { - console.log(); - process.stdin.removeAllListeners('keypress'); - tty.setRawMode(false); - if (!buf.trim().length) return self.password(str, mask, fn); - fn(buf); - return; - } - - if (key && key.ctrl && 'c' == key.name) { - console.log('%s', buf); - process.exit(); - } - - process.stdout.write(mask); - buf += c; - }).resume(); -}; - -/** - * Confirmation prompt with `str` and callback `fn(bool)` - * - * Examples: - * - * program.confirm('continue? ', function(ok){ - * console.log(' got %j', ok); - * process.stdin.destroy(); - * }); - * - * @param {String} str - * @param {Function} fn - * @api public - */ - - -Command.prototype.confirm = function(str, fn){ - var self = this; - this.prompt(str, function(ok){ - if (!ok.trim()) { - return self.confirm(str, fn); - } - fn(parseBool(ok)); - }); -}; - -/** - * Choice prompt with `list` of items and callback `fn(index, item)` - * - * Examples: - * - * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; - * - * console.log('Choose the coolest pet:'); - * program.choose(list, function(i){ - * console.log('you chose %d "%s"', i, list[i]); - * process.stdin.destroy(); - * }); - * - * @param {Array} list - * @param {Function} fn - * @api public - */ - -Command.prototype.choose = function(list, fn){ - var self = this; - - list.forEach(function(item, i){ - console.log(' %d) %s', i + 1, item); - }); - - function again() { - self.prompt(' : ', function(val){ - val = parseInt(val, 10) - 1; - if (null == list[val]) { - again(); - } else { - fn(val, list[val]); - } - }); - } - - again(); -}; - -/** - * Camel-case the given `flag` - * - * @param {String} flag - * @return {String} - * @api private - */ - -function camelcase(flag) { - return flag.split('-').reduce(function(str, word){ - return str + word[0].toUpperCase() + word.slice(1); - }); -} - -/** - * Parse a boolean `str`. - * - * @param {String} str - * @return {Boolean} - * @api private - */ - -function parseBool(str) { - return /^y|yes|ok|true$/i.test(str); -} - -/** - * Pad `str` to `width`. - * - * @param {String} str - * @param {Number} width - * @return {String} - * @api private - */ - -function pad(str, width) { - var len = Math.max(0, width - str.length); - return str + Array(len + 1).join(' '); -} - -/** - * Output help information if necessary - * - * @param {Command} command to output help for - * @param {Array} array of options to search for -h or --help - * @api private - */ - -function outputHelpIfNecessary(cmd, options) { - options = options || []; - for (var i = 0; i < options.length; i++) { - if (options[i] == '--help' || options[i] == '-h') { - process.on('exit', function() { - consoleFlush(cmd.helpInformation()); - cmd.emit('--help'); - consoleFlush(""); - }); - process.exit(); - } - - return true; - } -} diff --git a/contrib/escodegen.js b/contrib/escodegen.js deleted file mode 100644 index 2eaf1ad..0000000 --- a/contrib/escodegen.js +++ /dev/null @@ -1,843 +0,0 @@ -/* - Copyright (C) 2012 Ariya Hidayat - Copyright (C) 2012 Mathias Bynens - Copyright (C) 2012 Joost-Wim Boekesteijn - Copyright (C) 2012 Kris Kowal - Copyright (C) 2012 Yusuke Suzuki - Copyright (C) 2012 Arpad Borsos - Copyright (C) 2011 Ariya Hidayat - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/*jslint bitwise:true */ -/*global escodegen:true, exports:true, generateStatement: true*/ - -(function (exports) { - 'use strict'; - - var Syntax, - Precedence, - BinaryPrecedence, - base, - indent, - extra, - parse; - - Syntax = { - AssignmentExpression: 'AssignmentExpression', - ArrayExpression: 'ArrayExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - Program: 'Program', - Property: 'Property', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SwitchStatement: 'SwitchStatement', - SwitchCase: 'SwitchCase', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement' - }; - - Precedence = { - Sequence: 0, - Assignment: 1, - Conditional: 2, - LogicalOR: 3, - LogicalAND: 4, - LogicalXOR: 5, - BitwiseOR: 6, - BitwiseAND: 7, - Equality: 8, - Relational: 9, - BitwiseSHIFT: 10, - Additive: 11, - Multiplicative: 12, - Unary: 13, - Postfix: 14, - Call: 15, - New: 16, - Member: 17, - Primary: 18 - }; - - BinaryPrecedence = { - '||': Precedence.LogicalOR, - '&&': Precedence.LogicalAND, - '^': Precedence.LogicalXOR, - '|': Precedence.BitwiseOR, - '&': Precedence.BitwiseAND, - '==': Precedence.Equality, - '!=': Precedence.Equality, - '===': Precedence.Equality, - '!==': Precedence.Equality, - '<': Precedence.Relational, - '>': Precedence.Relational, - '<=': Precedence.Relational, - '>=': Precedence.Relational, - 'in': Precedence.Relational, - 'instanceof': Precedence.Relational, - '<<': Precedence.BitwiseSHIFT, - '>>': Precedence.BitwiseSHIFT, - '>>>': Precedence.BitwiseSHIFT, - '+': Precedence.Additive, - '-': Precedence.Additive, - '*': Precedence.Multiplicative, - '%': Precedence.Multiplicative, - '/': Precedence.Multiplicative - }; - - if (typeof Object.freeze === 'function') { - Object.freeze(Syntax); - Object.freeze(Precedence); - Object.freeze(BinaryPrecedence); - } - - function unicodeEscape(ch) { - var result, i; - result = ch.charCodeAt(0).toString(16); - for (i = result.length; i < 4; i += 1) { - result = '0' + result; - } - return '\\u' + result; - } - - function stringToArray(str) { - var length = str.length, - result = [], - i; - for (i = 0; i < length; i += 1) { - result[i] = str.charAt(i); - } - return result; - } - - function escapeString(str) { - var result = '', i, len, ch; - - if (typeof str[0] === 'undefined') { - str = stringToArray(str); - } - - for (i = 0, len = str.length; i < len; i += 1) { - ch = str[i]; - if ('\'\\\b\f\n\r\t'.indexOf(ch) >= 0) { - result += '\\'; - switch (ch) { - case '\'': - result += '\''; - break; - case '\\': - result += '\\'; - break; - case '\b': - result += 'b'; - break; - case '\f': - result += 'f'; - break; - case '\n': - result += 'n'; - break; - case '\r': - result += 'r'; - break; - case '\t': - result += 't'; - break; - } - } else if (ch < ' ' || ch.charCodeAt(0) >= 0x80) { - result += unicodeEscape(ch); - } else { - result += ch; - } - } - - return '\'' + result + '\''; - } - - function addIndent(stmt) { - return base + stmt; - } - - function parenthesize(text, current, should) { - return (current < should) ? '(' + text + ')' : text; - } - - function maybeBlock(stmt, suffix) { - var previousBase, result; - - if (stmt.type === Syntax.BlockStatement) { - result = ' ' + generateStatement(stmt); - if (suffix) { - return result + ' '; - } - return result; - } - - if (stmt.type === Syntax.EmptyStatement) { - result = ';'; - } else { - previousBase = base; - base += indent; - result = '\n' + addIndent(generateStatement(stmt)); - base = previousBase; - } - - if (suffix) { - return result + '\n' + addIndent(''); - } - return result; - } - - function generateFunctionBody(node) { - var result, i, len; - result = '('; - for (i = 0, len = node.params.length; i < len; i += 1) { - result += node.params[i].name; - if ((i + 1) < len) { - result += ', '; - } - } - return result + ')' + maybeBlock(node.body); - } - - function generateExpression(expr, precedence) { - var result, currentPrecedence, previousBase, i, len, raw; - - if (!precedence) { - precedence = Precedence.Sequence; - } - - switch (expr.type) { - case Syntax.SequenceExpression: - result = ''; - for (i = 0, len = expr.expressions.length; i < len; i += 1) { - result += generateExpression(expr.expressions[i], Precedence.Assignment); - if ((i + 1) < len) { - result += ', '; - } - } - result = parenthesize(result, Precedence.Sequence, precedence); - break; - - case Syntax.AssignmentExpression: - result = parenthesize( - generateExpression(expr.left, Precedence.Call) + ' ' + expr.operator + ' ' + - generateExpression(expr.right, Precedence.Assignment), - Precedence.Assignment, - precedence - ); - break; - - case Syntax.ConditionalExpression: - result = parenthesize( - generateExpression(expr.test, Precedence.LogicalOR) + ' ? ' + - generateExpression(expr.consequent, Precedence.Assignment) + ' : ' + - generateExpression(expr.alternate, Precedence.Assignment), - Precedence.Conditional, - precedence - ); - break; - - case Syntax.LogicalExpression: - case Syntax.BinaryExpression: - currentPrecedence = BinaryPrecedence[expr.operator]; - - result = generateExpression(expr.left, currentPrecedence) + - ' ' + expr.operator + ' ' + - generateExpression(expr.right, currentPrecedence + 1); - if (expr.operator === 'in') { - // TODO parenthesize only in allowIn = false case - result = '(' + result + ')'; - } else { - result = parenthesize(result, currentPrecedence, precedence); - } - break; - - case Syntax.CallExpression: - result = ''; - for (i = 0, len = expr['arguments'].length; i < len; i += 1) { - result += generateExpression(expr['arguments'][i], Precedence.Assignment); - if ((i + 1) < len) { - result += ', '; - } - } - result = parenthesize( - generateExpression(expr.callee, Precedence.Call) + '(' + result + ')', - Precedence.Call, - precedence - ); - break; - - case Syntax.NewExpression: - result = ''; - for (i = 0, len = expr['arguments'].length; i < len; i += 1) { - result += generateExpression(expr['arguments'][i], Precedence.Assignment); - if ((i + 1) < len) { - result += ', '; - } - } - result = parenthesize( - 'new ' + generateExpression(expr.callee, Precedence.New) + '(' + result + ')', - Precedence.New, - precedence - ); - break; - - case Syntax.MemberExpression: - result = generateExpression(expr.object, Precedence.Call); - if (expr.computed) { - result += '[' + generateExpression(expr.property) + ']'; - } else { - if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') { - if (result.indexOf('.') < 0) { - if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) { - result += '.'; - } - } - } - result += '.' + expr.property.name; - } - result = parenthesize(result, Precedence.Member, precedence); - break; - - case Syntax.UnaryExpression: - result = expr.operator; - if (result.length > 2) { - result += ' '; - } - result = parenthesize( - result + generateExpression(expr.argument, Precedence.Unary + - ( - expr.argument.type === Syntax.UnaryExpression && - expr.operator.length < 3 && - expr.argument.operator === expr.operator ? 1 : 0 - ) - ), - Precedence.Unary, - precedence - ); - break; - - case Syntax.UpdateExpression: - if (expr.prefix) { - result = parenthesize( - expr.operator + - generateExpression(expr.argument, Precedence.Unary), - Precedence.Unary, - precedence - ); - } else { - result = parenthesize( - generateExpression(expr.argument, Precedence.Postfix) + - expr.operator, - Precedence.Postfix, - precedence - ); - } - break; - - case Syntax.FunctionExpression: - result = 'function '; - if (expr.id) { - result += expr.id.name; - } - result += generateFunctionBody(expr); - break; - - case Syntax.ArrayExpression: - if (!expr.elements.length) { - result = '[]'; - break; - } - result = '[\n'; - previousBase = base; - base += indent; - for (i = 0, len = expr.elements.length; i < len; i += 1) { - if (!expr.elements[i]) { - result += addIndent(''); - if ((i + 1) === len) { - result += ','; - } - } else { - result += addIndent(generateExpression(expr.elements[i], Precedence.Assignment)); - } - if ((i + 1) < len) { - result += ',\n'; - } - } - base = previousBase; - result += '\n' + addIndent(']'); - break; - - case Syntax.Property: - if (expr.kind === 'get' || expr.kind === 'set') { - result = expr.kind + ' ' + generateExpression(expr.key) + - generateFunctionBody(expr.value); - } else { - result = generateExpression(expr.key) + ': ' + - generateExpression(expr.value, Precedence.Assignment); - } - break; - - case Syntax.ObjectExpression: - if (!expr.properties.length) { - result = '{}'; - break; - } - result = '{\n'; - previousBase = base; - base += indent; - for (i = 0, len = expr.properties.length; i < len; i += 1) { - result += addIndent(generateExpression(expr.properties[i])); - if ((i + 1) < len) { - result += ',\n'; - } - } - base = previousBase; - result += '\n' + addIndent('}'); - break; - - case Syntax.ThisExpression: - result = 'this'; - break; - - case Syntax.Identifier: - result = expr.name; - break; - - case Syntax.Literal: - if (expr.hasOwnProperty('raw') && parse) { - try { - raw = parse(expr.raw).body[0].expression; - if (raw.type === Syntax.Literal) { - if (raw.value === expr.value) { - result = expr.raw; - break; - } - } - } catch (e) { - // not use raw property - } - } - - if (expr.value === null) { - result = 'null'; - break; - } - - if (typeof expr.value === 'string') { - result = escapeString(expr.value); - break; - } - - if (typeof expr.value === 'number' && expr.value === Infinity) { - // Infinity is variable - result = '1e+1000'; - break; - } - - result = expr.value.toString(); - break; - - default: - break; - } - - if (result === undefined) { - throw new Error('Unknown expression type: ' + expr.type); - } - return result; - } - - function generateStatement(stmt) { - var i, len, result, previousBase; - - switch (stmt.type) { - case Syntax.BlockStatement: - result = '{\n'; - - previousBase = base; - base += indent; - for (i = 0, len = stmt.body.length; i < len; i += 1) { - result += addIndent(generateStatement(stmt.body[i])) + '\n'; - } - base = previousBase; - - result += addIndent('}'); - break; - - case Syntax.BreakStatement: - if (stmt.label) { - result = 'break ' + stmt.label.name + ';'; - } else { - result = 'break;'; - } - break; - - case Syntax.ContinueStatement: - if (stmt.label) { - result = 'continue ' + stmt.label.name + ';'; - } else { - result = 'continue;'; - } - break; - - case Syntax.DoWhileStatement: - result = 'do' + maybeBlock(stmt.body, true) + 'while (' + generateExpression(stmt.test) + ');'; - break; - - case Syntax.CatchClause: - previousBase = base; - base += indent; - result = ' catch (' + generateExpression(stmt.param) + ')'; - base = previousBase; - result += maybeBlock(stmt.body); - break; - - case Syntax.DebuggerStatement: - result = 'debugger;'; - break; - - case Syntax.EmptyStatement: - result = ';'; - break; - - case Syntax.ExpressionStatement: - result = generateExpression(stmt.expression); - // 12.4 '{', 'function' is not allowed in this position. - // wrap espression with parentheses - if (result[0] === '{' || result.indexOf('function ') === 0) { - result = '(' + result + ');'; - } else { - result += ';'; - } - break; - - case Syntax.VariableDeclarator: - if (stmt.init) { - result = stmt.id.name + ' = ' + generateExpression(stmt.init, Precedence.Assignment); - } else { - result = stmt.id.name; - } - break; - - case Syntax.VariableDeclaration: - result = stmt.kind + ' '; - // special path for - // var x = function () { - // }; - if (stmt.declarations.length === 1 && stmt.declarations[0].init && - stmt.declarations[0].init.type === Syntax.FunctionExpression) { - result += generateStatement(stmt.declarations[0]); - } else { - previousBase = base; - base += indent; - for (i = 0, len = stmt.declarations.length; i < len; i += 1) { - result += generateStatement(stmt.declarations[i]); - if ((i + 1) < len) { - result += ', '; - } - } - base = previousBase; - } - result += ';'; - break; - - case Syntax.ThrowStatement: - result = 'throw ' + generateExpression(stmt.argument) + ';'; - break; - - case Syntax.TryStatement: - result = 'try' + maybeBlock(stmt.block); - for (i = 0, len = stmt.handlers.length; i < len; i += 1) { - result += generateStatement(stmt.handlers[i]); - } - if (stmt.finalizer) { - result += ' finally' + maybeBlock(stmt.finalizer); - } - break; - - case Syntax.SwitchStatement: - previousBase = base; - base += indent; - result = 'switch (' + generateExpression(stmt.discriminant) + ') {\n'; - base = previousBase; - if (stmt.cases) { - for (i = 0, len = stmt.cases.length; i < len; i += 1) { - result += addIndent(generateStatement(stmt.cases[i])) + '\n'; - } - } - result += addIndent('}'); - break; - - case Syntax.SwitchCase: - previousBase = base; - base += indent; - if (stmt.test) { - result = 'case ' + generateExpression(stmt.test) + ':'; - } else { - result = 'default:'; - } - - i = 0; - len = stmt.consequent.length; - if (len && stmt.consequent[0].type === Syntax.BlockStatement) { - result += maybeBlock(stmt.consequent[0]); - i = 1; - } - - for (; i < len; i += 1) { - result += '\n' + addIndent(generateStatement(stmt.consequent[i])); - } - - base = previousBase; - break; - - case Syntax.IfStatement: - if (stmt.alternate) { - if (stmt.alternate.type === Syntax.IfStatement) { - previousBase = base; - base += indent; - result = 'if (' + generateExpression(stmt.test) + ')'; - base = previousBase; - result += maybeBlock(stmt.consequent, true) + 'else ' + generateStatement(stmt.alternate); - } else { - previousBase = base; - base += indent; - result = 'if (' + generateExpression(stmt.test) + ')'; - base = previousBase; - result += maybeBlock(stmt.consequent, true) + 'else' + maybeBlock(stmt.alternate); - } - } else { - previousBase = base; - base += indent; - result = 'if (' + generateExpression(stmt.test) + ')'; - base = previousBase; - result += maybeBlock(stmt.consequent); - } - break; - - case Syntax.ForStatement: - previousBase = base; - base += indent; - result = 'for ('; - if (stmt.init) { - if (stmt.init.type === Syntax.VariableDeclaration) { - result += generateStatement(stmt.init); - } else { - result += generateExpression(stmt.init) + ';'; - } - } else { - result += ';'; - } - - if (stmt.test) { - result += ' ' + generateExpression(stmt.test) + ';'; - } else { - result += ';'; - } - - if (stmt.update) { - result += ' ' + generateExpression(stmt.update) + ')'; - } else { - result += ')'; - } - base = previousBase; - - result += maybeBlock(stmt.body); - break; - - case Syntax.ForInStatement: - result = 'for ('; - if (stmt.left.type === Syntax.VariableDeclaration) { - previousBase = base; - base += indent + indent; - result += stmt.left.kind + ' ' + generateStatement(stmt.left.declarations[0]); - base = previousBase; - } else { - previousBase = base; - base += indent; - result += generateExpression(stmt.left, Precedence.Call); - base = previousBase; - } - - previousBase = base; - base += indent; - result += ' in ' + generateExpression(stmt.right) + ')'; - base = previousBase; - result += maybeBlock(stmt.body); - break; - - case Syntax.LabeledStatement: - result = stmt.label.name + ':' + maybeBlock(stmt.body); - break; - - case Syntax.Program: - result = ''; - for (i = 0, len = stmt.body.length; i < len; i += 1) { - result += generateStatement(stmt.body[i]); - if ((i + 1) < len) { - result += '\n'; - } - } - break; - - case Syntax.FunctionDeclaration: - result = 'function '; - if (stmt.id) { - result += stmt.id.name; - } - result += generateFunctionBody(stmt); - break; - - case Syntax.ReturnStatement: - if (stmt.argument) { - result = 'return ' + generateExpression(stmt.argument) + ';'; - } else { - result = 'return;'; - } - break; - - case Syntax.WhileStatement: - previousBase = base; - base += indent; - result = 'while (' + generateExpression(stmt.test) + ')'; - base = previousBase; - result += maybeBlock(stmt.body); - break; - - case Syntax.WithStatement: - previousBase = base; - base += indent; - result = 'with (' + generateExpression(stmt.object) + ')'; - base = previousBase; - result += maybeBlock(stmt.body); - break; - - default: - break; - } - - if (result === undefined) { - throw new Error('Unknown statement type: ' + stmt.type); - } - return result; - } - - function generate(node, options) { - if (typeof options !== 'undefined') { - base = options.base || ''; - indent = options.indent || ' '; - parse = options.parse; - } else { - base = ''; - indent = ' '; - parse = null; - } - - switch (node.type) { - case Syntax.BlockStatement: - case Syntax.BreakStatement: - case Syntax.CatchClause: - case Syntax.ContinueStatement: - case Syntax.DoWhileStatement: - case Syntax.DebuggerStatement: - case Syntax.EmptyStatement: - case Syntax.ExpressionStatement: - case Syntax.ForStatement: - case Syntax.ForInStatement: - case Syntax.FunctionDeclaration: - case Syntax.IfStatement: - case Syntax.LabeledStatement: - case Syntax.Program: - case Syntax.ReturnStatement: - case Syntax.SwitchStatement: - case Syntax.SwitchCase: - case Syntax.ThrowStatement: - case Syntax.TryStatement: - case Syntax.VariableDeclaration: - case Syntax.VariableDeclarator: - case Syntax.WhileStatement: - case Syntax.WithStatement: - return generateStatement(node); - - case Syntax.AssignmentExpression: - case Syntax.ArrayExpression: - case Syntax.BinaryExpression: - case Syntax.CallExpression: - case Syntax.ConditionalExpression: - case Syntax.FunctionExpression: - case Syntax.Identifier: - case Syntax.Literal: - case Syntax.LogicalExpression: - case Syntax.MemberExpression: - case Syntax.NewExpression: - case Syntax.ObjectExpression: - case Syntax.Property: - case Syntax.SequenceExpression: - case Syntax.ThisExpression: - case Syntax.UnaryExpression: - case Syntax.UpdateExpression: - return generateExpression(node); - - default: - break; - } - throw new Error('Unknown node type: ' + node.type); - } - - // Sync with package.json. - exports.version = '0.0.3-dev'; - - exports.generate = generate; - -}(typeof exports === 'undefined' ? (escodegen = {}) : exports)); -/* vim: set sw=4 ts=4 et tw=80 : */ \ No newline at end of file diff --git a/contrib/esprima.js b/contrib/esprima.js deleted file mode 100644 index d494204..0000000 --- a/contrib/esprima.js +++ /dev/null @@ -1,3846 +0,0 @@ -/* - Copyright (C) 2012 Ariya Hidayat - Copyright (C) 2012 Mathias Bynens - Copyright (C) 2012 Joost-Wim Boekesteijn - Copyright (C) 2012 Kris Kowal - Copyright (C) 2012 Yusuke Suzuki - Copyright (C) 2012 Arpad Borsos - Copyright (C) 2011 Ariya Hidayat - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/*jslint bitwise:true plusplus:true */ -/*global esprima:true, define:true, exports:true, window: true, -throwError: true, generateStatement: true, peek: true, -parseAssignmentExpression: true, parseBlock: true, parseExpression: true, -parseFunctionDeclaration: true, parseFunctionExpression: true, -parseFunctionSourceElements: true, parseVariableIdentifier: true, -parseLeftHandSideExpression: true, -parseStatement: true, parseSourceElement: true */ - -(function (root, factory) { - 'use strict'; - - // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, - // Rhino, and plain browser loading. - if (typeof define === 'function' && define.amd) { - define(['exports'], factory); - } else if (typeof exports !== 'undefined') { - factory(exports); - } else { - factory((root.esprima = {})); - } -}(this, function (exports) { - 'use strict'; - - var Token, - TokenName, - Syntax, - PropertyKind, - Messages, - Regex, - SyntaxTreeDelegate, - source, - strict, - index, - lineNumber, - lineStart, - length, - delegate, - lookahead, - state, - extra; - - Token = { - BooleanLiteral: 1, - EOF: 2, - Identifier: 3, - Keyword: 4, - NullLiteral: 5, - NumericLiteral: 6, - Punctuator: 7, - StringLiteral: 8 - }; - - TokenName = {}; - TokenName[Token.BooleanLiteral] = 'Boolean'; - TokenName[Token.EOF] = ''; - TokenName[Token.Identifier] = 'Identifier'; - TokenName[Token.Keyword] = 'Keyword'; - TokenName[Token.NullLiteral] = 'Null'; - TokenName[Token.NumericLiteral] = 'Numeric'; - TokenName[Token.Punctuator] = 'Punctuator'; - TokenName[Token.StringLiteral] = 'String'; - - Syntax = { - AssignmentExpression: 'AssignmentExpression', - ArrayExpression: 'ArrayExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - Program: 'Program', - Property: 'Property', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SwitchStatement: 'SwitchStatement', - SwitchCase: 'SwitchCase', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement' - }; - - PropertyKind = { - Data: 1, - Get: 2, - Set: 4 - }; - - // Error messages should be identical to V8. - Messages = { - UnexpectedToken: 'Unexpected token %0', - UnexpectedNumber: 'Unexpected number', - UnexpectedString: 'Unexpected string', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedEOS: 'Unexpected end of input', - NewlineAfterThrow: 'Illegal newline after throw', - InvalidRegExp: 'Invalid regular expression', - UnterminatedRegExp: 'Invalid regular expression: missing /', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', - MultipleDefaultsInSwitch: 'More than one default clause in switch statement', - NoCatchOrFinally: 'Missing catch or finally after try', - UnknownLabel: 'Undefined label \'%0\'', - Redeclaration: '%0 \'%1\' has already been declared', - IllegalContinue: 'Illegal continue statement', - IllegalBreak: 'Illegal break statement', - IllegalReturn: 'Illegal return statement', - StrictModeWith: 'Strict mode code may not include a with statement', - StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', - StrictParamDupe: 'Strict mode function may not have duplicate parameter names', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', - AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', - AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', - StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', - StrictReservedWord: 'Use of future reserved word in strict mode' - }; - - // See also tools/generate-unicode-regex.py. - Regex = { - NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), - NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') - }; - - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - - function assert(condition, message) { - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - - function isDecimalDigit(ch) { - return (ch >= 48 && ch <= 57); // 0..9 - } - - function isHexDigit(ch) { - return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; - } - - function isOctalDigit(ch) { - return '01234567'.indexOf(ch) >= 0; - } - - - // 7.2 White Space - - function isWhiteSpace(ch) { - return (ch === 32) || // space - (ch === 9) || // tab - (ch === 0xB) || - (ch === 0xC) || - (ch === 0xA0) || - (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); - } - - // 7.3 Line Terminators - - function isLineTerminator(ch) { - return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); - } - - // 7.6 Identifier Names and Identifiers - - function isIdentifierStart(ch) { - return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) - (ch >= 65 && ch <= 90) || // A..Z - (ch >= 97 && ch <= 122) || // a..z - (ch === 92) || // \ (backslash) - ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); - } - - function isIdentifierPart(ch) { - return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) - (ch >= 65 && ch <= 90) || // A..Z - (ch >= 97 && ch <= 122) || // a..z - (ch >= 48 && ch <= 57) || // 0..9 - (ch === 92) || // \ (backslash) - ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); - } - - // 7.6.1.2 Future Reserved Words - - function isFutureReservedWord(id) { - switch (id) { - case 'class': - case 'enum': - case 'export': - case 'extends': - case 'import': - case 'super': - return true; - default: - return false; - } - } - - function isStrictModeReservedWord(id) { - switch (id) { - case 'implements': - case 'interface': - case 'package': - case 'private': - case 'protected': - case 'public': - case 'static': - case 'yield': - case 'let': - return true; - default: - return false; - } - } - - function isRestrictedWord(id) { - return id === 'eval' || id === 'arguments'; - } - - // 7.6.1.1 Keywords - - function isKeyword(id) { - if (strict && isStrictModeReservedWord(id)) { - return true; - } - - // 'const' is specialized as Keyword in V8. - // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. - // Some others are from future reserved words. - - switch (id.length) { - case 2: - return (id === 'if') || (id === 'in') || (id === 'do'); - case 3: - return (id === 'var') || (id === 'for') || (id === 'new') || - (id === 'try') || (id === 'let'); - case 4: - return (id === 'this') || (id === 'else') || (id === 'case') || - (id === 'void') || (id === 'with') || (id === 'enum'); - case 5: - return (id === 'while') || (id === 'break') || (id === 'catch') || - (id === 'throw') || (id === 'const') || (id === 'yield') || - (id === 'class') || (id === 'super'); - case 6: - return (id === 'return') || (id === 'typeof') || (id === 'delete') || - (id === 'switch') || (id === 'export') || (id === 'import'); - case 7: - return (id === 'default') || (id === 'finally') || (id === 'extends'); - case 8: - return (id === 'function') || (id === 'continue') || (id === 'debugger'); - case 10: - return (id === 'instanceof'); - default: - return false; - } - } - - // 7.4 Comments - - function skipComment() { - var ch, blockComment, lineComment; - - blockComment = false; - lineComment = false; - - while (index < length) { - ch = source.charCodeAt(index); - - if (lineComment) { - ++index; - if (isLineTerminator(ch)) { - lineComment = false; - if (ch === 13 && source.charCodeAt(index) === 10) { - ++index; - } - ++lineNumber; - lineStart = index; - } - } else if (blockComment) { - if (isLineTerminator(ch)) { - if (ch === 13 && source.charCodeAt(index + 1) === 10) { - ++index; - } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - ch = source.charCodeAt(index++); - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - // Block comment ends with '*/' (char #42, char #47). - if (ch === 42) { - ch = source.charCodeAt(index); - if (ch === 47) { - ++index; - blockComment = false; - } - } - } - } else if (ch === 47) { - ch = source.charCodeAt(index + 1); - // Line comment starts with '//' (char #47, char #47). - if (ch === 47) { - index += 2; - lineComment = true; - } else if (ch === 42) { - // Block comment starts with '/*' (char #47, char #42). - index += 2; - blockComment = true; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - break; - } - } else if (isWhiteSpace(ch)) { - ++index; - } else if (isLineTerminator(ch)) { - ++index; - if (ch === 13 && source.charCodeAt(index) === 10) { - ++index; - } - ++lineNumber; - lineStart = index; - } else { - break; - } - } - } - - function scanHexEscape(prefix) { - var i, len, ch, code = 0; - - len = (prefix === 'u') ? 4 : 2; - for (i = 0; i < len; ++i) { - if (index < length && isHexDigit(source[index])) { - ch = source[index++]; - code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); - } else { - return ''; - } - } - return String.fromCharCode(code); - } - - function getEscapedIdentifier() { - var ch, id, type; - - ch = source.charCodeAt(index++); - id = String.fromCharCode(ch); - - // '\u' (char #92, char #117) denotes an escaped character. - if (ch === 92) { - if (source.charCodeAt(index) !== 117) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - ++index; - ch = scanHexEscape('u'); - if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - id = ch; - } - - while (index < length) { - ch = source.charCodeAt(index); - if (!isIdentifierPart(ch)) { - break; - } - ++index; - id += String.fromCharCode(ch); - - // '\u' (char #92, char #117) denotes an escaped character. - if (ch === 92) { - id = id.substr(0, id.length - 1); - if (source.charCodeAt(index) !== 117) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - ++index; - ch = scanHexEscape('u'); - if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - id += ch; - } - } - - return id; - } - - function getIdentifier() { - var start, ch; - - start = index++; - while (index < length) { - ch = source.charCodeAt(index); - if (ch === 92) { - // Blackslash (char #92) marks Unicode escape sequence. - index = start; - return getEscapedIdentifier(); - } - if (isIdentifierPart(ch)) { - ++index; - } else { - break; - } - } - - return source.slice(start, index); - } - - function scanIdentifier() { - var start, id, type; - - start = index; - - // Backslash (char #92) starts an escaped character. - id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); - - // There is no keyword or literal with only one character. - // Thus, it must be an identifier. - if (id.length === 1) { - type = Token.Identifier; - } else if (isKeyword(id)) { - type = Token.Keyword; - } else if (id === 'null') { - type = Token.NullLiteral; - } else if (id === 'true' || id === 'false') { - type = Token.BooleanLiteral; - } else { - type = Token.Identifier; - } - - return { - type: type, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - - // 7.7 Punctuators - - function scanPunctuator() { - var start = index, - code = source.charCodeAt(index), - code2, - ch1 = source[index], - ch2, - ch3, - ch4; - - switch (code) { - - // Check for most common single-character punctuators. - case 46: // . dot - case 40: // ( open bracket - case 41: // ) close bracket - case 59: // ; semicolon - case 44: // , comma - case 123: // { open curly brace - case 125: // } close curly brace - case 91: // [ - case 93: // ] - case 58: // : - case 63: // ? - case 126: // ~ - ++index; - return { - type: Token.Punctuator, - value: String.fromCharCode(code), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - - default: - code2 = source.charCodeAt(index + 1); - - // '=' (char #61) marks an assignment or comparison operator. - if (code2 === 61) { - switch (code) { - case 37: // % - case 38: // & - case 42: // *: - case 43: // + - case 45: // - - case 47: // / - case 60: // < - case 62: // > - case 94: // ^ - case 124: // | - index += 2; - return { - type: Token.Punctuator, - value: String.fromCharCode(code) + String.fromCharCode(code2), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - - case 33: // ! - case 61: // = - index += 2; - - // !== and === - if (source.charCodeAt(index) === 61) { - ++index; - } - return { - type: Token.Punctuator, - value: source.slice(start, index), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - default: - break; - } - } - break; - } - - // Peek more characters. - - ch2 = source[index + 1]; - ch3 = source[index + 2]; - ch4 = source[index + 3]; - - // 4-character punctuator: >>>= - - if (ch1 === '>' && ch2 === '>' && ch3 === '>') { - if (ch4 === '=') { - index += 4; - return { - type: Token.Punctuator, - value: '>>>=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - // 3-character punctuators: === !== >>> <<= >>= - - if (ch1 === '>' && ch2 === '>' && ch3 === '>') { - index += 3; - return { - type: Token.Punctuator, - value: '>>>', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '<' && ch2 === '<' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '<<=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '>' && ch2 === '>' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '>>=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 2-character punctuators: <= >= == != ++ -- << >> && || - // += -= *= %= &= |= ^= /= - - if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { - if ('+-<>&|'.indexOf(ch2) >= 0) { - index += 2; - return { - type: Token.Punctuator, - value: ch1 + ch2, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { - ++index; - return { - type: Token.Punctuator, - value: ch1, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - // 7.8.3 Numeric Literals - - function scanNumericLiteral() { - var number, start, ch; - - ch = source[index]; - assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), - 'Numeric literal must start with a decimal digit or a decimal point'); - - start = index; - number = ''; - if (ch !== '.') { - number = source[index++]; - ch = source[index]; - - // Hex number starts with '0x'. - // Octal number starts with '0'. - if (number === '0') { - if (ch === 'x' || ch === 'X') { - number += source[index++]; - while (index < length) { - ch = source[index]; - if (!isHexDigit(ch)) { - break; - } - number += source[index++]; - } - - if (number.length <= 2) { - // only 0x - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - if (index < length) { - ch = source[index]; - if (isIdentifierStart(ch.charCodeAt(0))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - return { - type: Token.NumericLiteral, - value: parseInt(number, 16), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - if (isOctalDigit(ch)) { - number += source[index++]; - while (index < length) { - ch = source[index]; - if (!isOctalDigit(ch)) { - break; - } - number += source[index++]; - } - - if (index < length) { - ch = source.charCodeAt(index); - if (isIdentifierStart(ch) || isDecimalDigit(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - return { - type: Token.NumericLiteral, - value: parseInt(number, 8), - octal: true, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // decimal number starts with '0' such as '09' is illegal. - if (ch && isDecimalDigit(ch.charCodeAt(0))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - while (index < length) { - if (!isDecimalDigit(source.charCodeAt(index))) { - ch = source[index]; - break; - } - number += source[index++]; - } - } - - if (ch === '.') { - number += source[index++]; - while (index < length) { - if (!isDecimalDigit(source.charCodeAt(index))) { - ch = source[index]; - break; - } - number += source[index++]; - } - } - - if (ch === 'e' || ch === 'E') { - number += source[index++]; - - ch = source[index]; - if (ch === '+' || ch === '-') { - number += source[index++]; - } - - ch = source[index]; - if (ch && isDecimalDigit(ch.charCodeAt(0))) { - number += source[index++]; - while (index < length) { - if (!isDecimalDigit(source.charCodeAt(index))) { - ch = source[index]; - break; - } - number += source[index++]; - } - } else { - ch = 'character ' + ch; - if (index >= length) { - ch = ''; - } - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - if (index < length) { - if (isIdentifierStart(source.charCodeAt(index))) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - return { - type: Token.NumericLiteral, - value: parseFloat(number), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 7.8.4 String Literals - - function scanStringLiteral() { - var str = '', quote, start, ch, code, unescaped, restore, octal = false; - - quote = source[index]; - assert((quote === '\'' || quote === '"'), - 'String literal must starts with a quote'); - - start = index; - ++index; - - while (index < length) { - ch = source[index++]; - - if (ch === quote) { - quote = ''; - break; - } else if (ch === '\\') { - ch = source[index++]; - if (!ch || !isLineTerminator(ch.charCodeAt(0))) { - switch (ch) { - case 'n': - str += '\n'; - break; - case 'r': - str += '\r'; - break; - case 't': - str += '\t'; - break; - case 'u': - case 'x': - restore = index; - unescaped = scanHexEscape(ch); - if (unescaped) { - str += unescaped; - } else { - index = restore; - str += ch; - } - break; - case 'b': - str += '\b'; - break; - case 'f': - str += '\f'; - break; - case 'v': - str += '\v'; - break; - - default: - if (isOctalDigit(ch)) { - code = '01234567'.indexOf(ch); - - // \0 is not octal escape sequence - if (code !== 0) { - octal = true; - } - - if (index < length && isOctalDigit(source[index])) { - octal = true; - code = code * 8 + '01234567'.indexOf(source[index++]); - - // 3 digits are only allowed when string starts - // with 0, 1, 2, 3 - if ('0123'.indexOf(ch) >= 0 && - index < length && - isOctalDigit(source[index])) { - code = code * 8 + '01234567'.indexOf(source[index++]); - } - } - str += String.fromCharCode(code); - } else { - str += ch; - } - break; - } - } else { - ++lineNumber; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - } - } else if (isLineTerminator(ch.charCodeAt(0))) { - break; - } else { - str += ch; - } - } - - if (quote !== '') { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - return { - type: Token.StringLiteral, - value: str, - octal: octal, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - function scanRegExp() { - var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; - - lookahead = null; - skipComment(); - - start = index; - ch = source[index]; - assert(ch === '/', 'Regular expression literal must start with a slash'); - str = source[index++]; - - while (index < length) { - ch = source[index++]; - str += ch; - if (classMarker) { - if (ch === ']') { - classMarker = false; - } - } else { - if (ch === '\\') { - ch = source[index++]; - // ECMA-262 7.8.5 - if (isLineTerminator(ch.charCodeAt(0))) { - throwError({}, Messages.UnterminatedRegExp); - } - str += ch; - } else if (ch === '/') { - terminated = true; - break; - } else if (ch === '[') { - classMarker = true; - } else if (isLineTerminator(ch.charCodeAt(0))) { - throwError({}, Messages.UnterminatedRegExp); - } - } - } - - if (!terminated) { - throwError({}, Messages.UnterminatedRegExp); - } - - // Exclude leading and trailing slash. - pattern = str.substr(1, str.length - 2); - - flags = ''; - while (index < length) { - ch = source[index]; - if (!isIdentifierPart(ch.charCodeAt(0))) { - break; - } - - ++index; - if (ch === '\\' && index < length) { - ch = source[index]; - if (ch === 'u') { - ++index; - restore = index; - ch = scanHexEscape('u'); - if (ch) { - flags += ch; - for (str += '\\u'; restore < index; ++restore) { - str += source[restore]; - } - } else { - index = restore; - flags += 'u'; - str += '\\u'; - } - } else { - str += '\\'; - } - } else { - flags += ch; - str += ch; - } - } - - try { - value = new RegExp(pattern, flags); - } catch (e) { - throwError({}, Messages.InvalidRegExp); - } - - peek(); - - return { - literal: str, - value: value, - range: [start, index] - }; - } - - function isIdentifierName(token) { - return token.type === Token.Identifier || - token.type === Token.Keyword || - token.type === Token.BooleanLiteral || - token.type === Token.NullLiteral; - } - - function advance() { - var ch; - - skipComment(); - - if (index >= length) { - return { - type: Token.EOF, - lineNumber: lineNumber, - lineStart: lineStart, - range: [index, index] - }; - } - - ch = source.charCodeAt(index); - - // Very common: ( and ) and ; - if (ch === 40 || ch === 41 || ch === 58) { - return scanPunctuator(); - } - - // String literal starts with single quote (#39) or double quote (#34). - if (ch === 39 || ch === 34) { - return scanStringLiteral(); - } - - if (isIdentifierStart(ch)) { - return scanIdentifier(); - } - - // Dot (.) char #46 can also start a floating-point number, hence the need - // to check the next character. - if (ch === 46) { - if (isDecimalDigit(source.charCodeAt(index + 1))) { - return scanNumericLiteral(); - } - return scanPunctuator(); - } - - if (isDecimalDigit(ch)) { - return scanNumericLiteral(); - } - - return scanPunctuator(); - } - - function lex() { - var token; - - token = lookahead; - index = token.range[1]; - lineNumber = token.lineNumber; - lineStart = token.lineStart; - - lookahead = advance(); - - index = token.range[1]; - lineNumber = token.lineNumber; - lineStart = token.lineStart; - - return token; - } - - function peek() { - var pos, line, start; - - pos = index; - line = lineNumber; - start = lineStart; - lookahead = advance(); - index = pos; - lineNumber = line; - lineStart = start; - } - - SyntaxTreeDelegate = { - - name: 'SyntaxTree', - - createArrayExpression: function (elements) { - return { - type: Syntax.ArrayExpression, - elements: elements - }; - }, - - createAssignmentExpression: function (operator, left, right) { - return { - type: Syntax.AssignmentExpression, - operator: operator, - left: left, - right: right - }; - }, - - createBinaryExpression: function (operator, left, right) { - return { - type: Syntax.BinaryExpression, - operator: operator, - left: left, - right: right - }; - }, - - createBlockStatement: function (body) { - return { - type: Syntax.BlockStatement, - body: body - }; - }, - - createBreakStatement: function (label) { - return { - type: Syntax.BreakStatement, - label: label - }; - }, - - createCallExpression: function (callee, args) { - return { - type: Syntax.CallExpression, - callee: callee, - 'arguments': args - }; - }, - - createCatchClause: function (param, body) { - return { - type: Syntax.CatchClause, - param: param, - body: body - }; - }, - - createConditionalExpression: function (test, consequent, alternate) { - return { - type: Syntax.ConditionalExpression, - test: test, - consequent: consequent, - alternate: alternate - }; - }, - - createContinueStatement: function (label) { - return { - type: Syntax.ContinueStatement, - label: label - }; - }, - - createDebuggerStatement: function () { - return { - type: Syntax.DebuggerStatement - }; - }, - - createDoWhileStatement: function (body, test) { - return { - type: Syntax.DoWhileStatement, - body: body, - test: test - }; - }, - - createEmptyStatement: function () { - return { - type: Syntax.EmptyStatement - }; - }, - - createExpressionStatement: function (expression) { - return { - type: Syntax.ExpressionStatement, - expression: expression - }; - }, - - createForStatement: function (init, test, update, body) { - return { - type: Syntax.ForStatement, - init: init, - test: test, - update: update, - body: body - }; - }, - - createForInStatement: function (left, right, body) { - return { - type: Syntax.ForInStatement, - left: left, - right: right, - body: body, - each: false - }; - }, - - createFunctionDeclaration: function (id, params, defaults, body) { - return { - type: Syntax.FunctionDeclaration, - id: id, - params: params, - defaults: defaults, - body: body, - rest: null, - generator: false, - expression: false - }; - }, - - createFunctionExpression: function (id, params, defaults, body) { - return { - type: Syntax.FunctionExpression, - id: id, - params: params, - defaults: defaults, - body: body, - rest: null, - generator: false, - expression: false - }; - }, - - createIdentifier: function (name) { - return { - type: Syntax.Identifier, - name: name - }; - }, - - createIfStatement: function (test, consequent, alternate) { - return { - type: Syntax.IfStatement, - test: test, - consequent: consequent, - alternate: alternate - }; - }, - - createLabeledStatement: function (label, body) { - return { - type: Syntax.LabeledStatement, - label: label, - body: body - }; - }, - - createLiteral: function (token) { - return { - type: Syntax.Literal, - value: token.value, - raw: source.slice(token.range[0], token.range[1]) - }; - }, - - createLogicalExpression: function (operator, left, right) { - return { - type: Syntax.LogicalExpression, - operator: operator, - left: left, - right: right - }; - }, - - createMemberExpression: function (accessor, object, property) { - return { - type: Syntax.MemberExpression, - computed: accessor === '[', - object: object, - property: property - }; - }, - - createNewExpression: function (callee, args) { - return { - type: Syntax.NewExpression, - callee: callee, - 'arguments': args - }; - }, - - createObjectExpression: function (properties) { - return { - type: Syntax.ObjectExpression, - properties: properties - }; - }, - - createPostfixExpression: function (operator, argument) { - return { - type: Syntax.UpdateExpression, - operator: operator, - argument: argument, - prefix: false - }; - }, - - createProgram: function (body) { - return { - type: Syntax.Program, - body: body - }; - }, - - createProperty: function (kind, key, value) { - return { - type: Syntax.Property, - key: key, - value: value, - kind: kind - }; - }, - - createReturnStatement: function (argument) { - return { - type: Syntax.ReturnStatement, - argument: argument - }; - }, - - createSequenceExpression: function (expressions) { - return { - type: Syntax.SequenceExpression, - expressions: expressions - }; - }, - - createSwitchCase: function (test, consequent) { - return { - type: Syntax.SwitchCase, - test: test, - consequent: consequent - }; - }, - - createSwitchStatement: function (discriminant, cases) { - return { - type: Syntax.SwitchStatement, - discriminant: discriminant, - cases: cases - }; - }, - - createThisExpression: function () { - return { - type: Syntax.ThisExpression - }; - }, - - createThrowStatement: function (argument) { - return { - type: Syntax.ThrowStatement, - argument: argument - }; - }, - - createTryStatement: function (block, guardedHandlers, handlers, finalizer) { - return { - type: Syntax.TryStatement, - block: block, - guardedHandlers: guardedHandlers, - handlers: handlers, - finalizer: finalizer - }; - }, - - createUnaryExpression: function (operator, argument) { - if (operator === '++' || operator === '--') { - return { - type: Syntax.UpdateExpression, - operator: operator, - argument: argument, - prefix: true - }; - } - return { - type: Syntax.UnaryExpression, - operator: operator, - argument: argument - }; - }, - - createVariableDeclaration: function (declarations, kind) { - return { - type: Syntax.VariableDeclaration, - declarations: declarations, - kind: kind - }; - }, - - createVariableDeclarator: function (id, init) { - return { - type: Syntax.VariableDeclarator, - id: id, - init: init - }; - }, - - createWhileStatement: function (test, body) { - return { - type: Syntax.WhileStatement, - test: test, - body: body - }; - }, - - createWithStatement: function (object, body) { - return { - type: Syntax.WithStatement, - object: object, - body: body - }; - } - }; - - // Return true if there is a line terminator before the next token. - - function peekLineTerminator() { - var pos, line, start, found; - - pos = index; - line = lineNumber; - start = lineStart; - skipComment(); - found = lineNumber !== line; - index = pos; - lineNumber = line; - lineStart = start; - - return found; - } - - // Throw an exception - - function throwError(token, messageFormat) { - var error, - args = Array.prototype.slice.call(arguments, 2), - msg = messageFormat.replace( - /%(\d)/g, - function (whole, index) { - return args[index] || ''; - } - ); - - if (typeof token.lineNumber === 'number') { - error = new Error('Line ' + token.lineNumber + ': ' + msg); - error.index = token.range[0]; - error.lineNumber = token.lineNumber; - error.column = token.range[0] - lineStart + 1; - } else { - error = new Error('Line ' + lineNumber + ': ' + msg); - error.index = index; - error.lineNumber = lineNumber; - error.column = index - lineStart + 1; - } - - throw error; - } - - function throwErrorTolerant() { - try { - throwError.apply(null, arguments); - } catch (e) { - if (extra.errors) { - extra.errors.push(e); - } else { - throw e; - } - } - } - - - // Throw an exception because of the token. - - function throwUnexpected(token) { - if (token.type === Token.EOF) { - throwError(token, Messages.UnexpectedEOS); - } - - if (token.type === Token.NumericLiteral) { - throwError(token, Messages.UnexpectedNumber); - } - - if (token.type === Token.StringLiteral) { - throwError(token, Messages.UnexpectedString); - } - - if (token.type === Token.Identifier) { - throwError(token, Messages.UnexpectedIdentifier); - } - - if (token.type === Token.Keyword) { - if (isFutureReservedWord(token.value)) { - throwError(token, Messages.UnexpectedReserved); - } else if (strict && isStrictModeReservedWord(token.value)) { - throwErrorTolerant(token, Messages.StrictReservedWord); - return; - } - throwError(token, Messages.UnexpectedToken, token.value); - } - - // BooleanLiteral, NullLiteral, or Punctuator. - throwError(token, Messages.UnexpectedToken, token.value); - } - - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - - function expect(value) { - var token = lex(); - if (token.type !== Token.Punctuator || token.value !== value) { - throwUnexpected(token); - } - } - - // Expect the next token to match the specified keyword. - // If not, an exception will be thrown. - - function expectKeyword(keyword) { - var token = lex(); - if (token.type !== Token.Keyword || token.value !== keyword) { - throwUnexpected(token); - } - } - - // Return true if the next token matches the specified punctuator. - - function match(value) { - return lookahead.type === Token.Punctuator && lookahead.value === value; - } - - // Return true if the next token matches the specified keyword - - function matchKeyword(keyword) { - return lookahead.type === Token.Keyword && lookahead.value === keyword; - } - - // Return true if the next token is an assignment operator - - function matchAssign() { - var op; - - if (lookahead.type !== Token.Punctuator) { - return false; - } - op = lookahead.value; - return op === '=' || - op === '*=' || - op === '/=' || - op === '%=' || - op === '+=' || - op === '-=' || - op === '<<=' || - op === '>>=' || - op === '>>>=' || - op === '&=' || - op === '^=' || - op === '|='; - } - - function consumeSemicolon() { - var line; - - // Catch the very common case first: immediately a semicolon (char #59). - if (source.charCodeAt(index) === 59) { - lex(); - return; - } - - line = lineNumber; - skipComment(); - if (lineNumber !== line) { - return; - } - - if (match(';')) { - lex(); - return; - } - - if (lookahead.type !== Token.EOF && !match('}')) { - throwUnexpected(lookahead); - } - } - - // Return true if provided expression is LeftHandSideExpression - - function isLeftHandSide(expr) { - return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; - } - - // 11.1.4 Array Initialiser - - function parseArrayInitialiser() { - var elements = []; - - expect('['); - - while (!match(']')) { - if (match(',')) { - lex(); - elements.push(null); - } else { - elements.push(parseAssignmentExpression()); - - if (!match(']')) { - expect(','); - } - } - } - - expect(']'); - - return delegate.createArrayExpression(elements); - } - - // 11.1.5 Object Initialiser - - function parsePropertyFunction(param, first) { - var previousStrict, body; - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (first && strict && isRestrictedWord(param[0].name)) { - throwErrorTolerant(first, Messages.StrictParamName); - } - strict = previousStrict; - return delegate.createFunctionExpression(null, param, [], body); - } - - function parseObjectPropertyKey() { - var token = lex(); - - // Note: This function is called only from parseObjectProperty(), where - // EOF and Punctuator tokens are already filtered out. - - if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { - if (strict && token.octal) { - throwErrorTolerant(token, Messages.StrictOctalLiteral); - } - return delegate.createLiteral(token); - } - - return delegate.createIdentifier(token.value); - } - - function parseObjectProperty() { - var token, key, id, value, param; - - token = lookahead; - - if (token.type === Token.Identifier) { - - id = parseObjectPropertyKey(); - - // Property Assignment: Getter and Setter. - - if (token.value === 'get' && !match(':')) { - key = parseObjectPropertyKey(); - expect('('); - expect(')'); - value = parsePropertyFunction([]); - return delegate.createProperty('get', key, value); - } - if (token.value === 'set' && !match(':')) { - key = parseObjectPropertyKey(); - expect('('); - token = lookahead; - if (token.type !== Token.Identifier) { - throwUnexpected(lex()); - } - param = [ parseVariableIdentifier() ]; - expect(')'); - value = parsePropertyFunction(param, token); - return delegate.createProperty('set', key, value); - } - expect(':'); - value = parseAssignmentExpression(); - return delegate.createProperty('init', id, value); - } - if (token.type === Token.EOF || token.type === Token.Punctuator) { - throwUnexpected(token); - } else { - key = parseObjectPropertyKey(); - expect(':'); - value = parseAssignmentExpression(); - return delegate.createProperty('init', key, value); - } - } - - function parseObjectInitialiser() { - var properties = [], property, name, kind, map = {}, toString = String; - - expect('{'); - - while (!match('}')) { - property = parseObjectProperty(); - - if (property.key.type === Syntax.Identifier) { - name = property.key.name; - } else { - name = toString(property.key.value); - } - kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; - if (Object.prototype.hasOwnProperty.call(map, name)) { - if (map[name] === PropertyKind.Data) { - if (strict && kind === PropertyKind.Data) { - throwErrorTolerant({}, Messages.StrictDuplicateProperty); - } else if (kind !== PropertyKind.Data) { - throwErrorTolerant({}, Messages.AccessorDataProperty); - } - } else { - if (kind === PropertyKind.Data) { - throwErrorTolerant({}, Messages.AccessorDataProperty); - } else if (map[name] & kind) { - throwErrorTolerant({}, Messages.AccessorGetSet); - } - } - map[name] |= kind; - } else { - map[name] = kind; - } - - properties.push(property); - - if (!match('}')) { - expect(','); - } - } - - expect('}'); - - return delegate.createObjectExpression(properties); - } - - // 11.1.6 The Grouping Operator - - function parseGroupExpression() { - var expr; - - expect('('); - - expr = parseExpression(); - - expect(')'); - - return expr; - } - - - // 11.1 Primary Expressions - - function parsePrimaryExpression() { - var type, token; - - type = lookahead.type; - - if (type === Token.Identifier) { - return delegate.createIdentifier(lex().value); - } - - if (type === Token.StringLiteral || type === Token.NumericLiteral) { - if (strict && lookahead.octal) { - throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); - } - return delegate.createLiteral(lex()); - } - - if (type === Token.Keyword) { - if (matchKeyword('this')) { - lex(); - return delegate.createThisExpression(); - } - - if (matchKeyword('function')) { - return parseFunctionExpression(); - } - } - - if (type === Token.BooleanLiteral) { - token = lex(); - token.value = (token.value === 'true'); - return delegate.createLiteral(token); - } - - if (type === Token.NullLiteral) { - token = lex(); - token.value = null; - return delegate.createLiteral(token); - } - - if (match('[')) { - return parseArrayInitialiser(); - } - - if (match('{')) { - return parseObjectInitialiser(); - } - - if (match('(')) { - return parseGroupExpression(); - } - - if (match('/') || match('/=')) { - return delegate.createLiteral(scanRegExp()); - } - - return throwUnexpected(lex()); - } - - // 11.2 Left-Hand-Side Expressions - - function parseArguments() { - var args = []; - - expect('('); - - if (!match(')')) { - while (index < length) { - args.push(parseAssignmentExpression()); - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - return args; - } - - function parseNonComputedProperty() { - var token = lex(); - - if (!isIdentifierName(token)) { - throwUnexpected(token); - } - - return delegate.createIdentifier(token.value); - } - - function parseNonComputedMember() { - expect('.'); - - return parseNonComputedProperty(); - } - - function parseComputedMember() { - var expr; - - expect('['); - - expr = parseExpression(); - - expect(']'); - - return expr; - } - - function parseNewExpression() { - var callee, args; - - expectKeyword('new'); - callee = parseLeftHandSideExpression(); - args = match('(') ? parseArguments() : []; - - return delegate.createNewExpression(callee, args); - } - - function parseLeftHandSideExpressionAllowCall() { - var expr, args, property; - - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - - while (match('.') || match('[') || match('(')) { - if (match('(')) { - args = parseArguments(); - expr = delegate.createCallExpression(expr, args); - } else if (match('[')) { - property = parseComputedMember(); - expr = delegate.createMemberExpression('[', expr, property); - } else { - property = parseNonComputedMember(); - expr = delegate.createMemberExpression('.', expr, property); - } - } - - return expr; - } - - - function parseLeftHandSideExpression() { - var expr, property; - - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - - while (match('.') || match('[')) { - if (match('[')) { - property = parseComputedMember(); - expr = delegate.createMemberExpression('[', expr, property); - } else { - property = parseNonComputedMember(); - expr = delegate.createMemberExpression('.', expr, property); - } - } - - return expr; - } - - // 11.3 Postfix Expressions - - function parsePostfixExpression() { - var expr = parseLeftHandSideExpressionAllowCall(), token; - - if (lookahead.type !== Token.Punctuator) { - return expr; - } - - if ((match('++') || match('--')) && !peekLineTerminator()) { - // 11.3.1, 11.3.2 - if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { - throwErrorTolerant({}, Messages.StrictLHSPostfix); - } - - if (!isLeftHandSide(expr)) { - throwError({}, Messages.InvalidLHSInAssignment); - } - - token = lex(); - expr = delegate.createPostfixExpression(token.value, expr); - } - - return expr; - } - - // 11.4 Unary Operators - - function parseUnaryExpression() { - var token, expr; - - if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { - return parsePostfixExpression(); - } - - if (match('++') || match('--')) { - token = lex(); - expr = parseUnaryExpression(); - // 11.4.4, 11.4.5 - if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { - throwErrorTolerant({}, Messages.StrictLHSPrefix); - } - - if (!isLeftHandSide(expr)) { - throwError({}, Messages.InvalidLHSInAssignment); - } - - return delegate.createUnaryExpression(token.value, expr); - } - - if (match('+') || match('-') || match('~') || match('!')) { - token = lex(); - expr = parseUnaryExpression(); - return delegate.createUnaryExpression(token.value, expr); - } - - if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { - token = lex(); - expr = parseUnaryExpression(); - expr = delegate.createUnaryExpression(token.value, expr); - if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { - throwErrorTolerant({}, Messages.StrictDelete); - } - return expr; - } - - return parsePostfixExpression(); - } - - function binaryPrecedence(token, allowIn) { - var prec = 0; - - if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { - return 0; - } - - switch (token.value) { - case '||': - prec = 1; - break; - - case '&&': - prec = 2; - break; - - case '|': - prec = 3; - break; - - case '^': - prec = 4; - break; - - case '&': - prec = 5; - break; - - case '==': - case '!=': - case '===': - case '!==': - prec = 6; - break; - - case '<': - case '>': - case '<=': - case '>=': - case 'instanceof': - prec = 7; - break; - - case 'in': - prec = allowIn ? 7 : 0; - break; - - case '<<': - case '>>': - case '>>>': - prec = 8; - break; - - case '+': - case '-': - prec = 9; - break; - - case '*': - case '/': - case '%': - prec = 11; - break; - - default: - break; - } - - return prec; - } - - // 11.5 Multiplicative Operators - // 11.6 Additive Operators - // 11.7 Bitwise Shift Operators - // 11.8 Relational Operators - // 11.9 Equality Operators - // 11.10 Binary Bitwise Operators - // 11.11 Binary Logical Operators - - // Reduce: make a binary expression from the three topmost entries. - function reduceBinary(stack) { - var right = stack.pop(), - operator = stack.pop().value, - left = stack.pop(); - - - if (operator === '||' || operator === '&&') { - stack.push(delegate.createLogicalExpression(operator, left, right)); - } else { - stack.push(delegate.createBinaryExpression(operator, left, right)); - } - } - - function parseBinaryExpression() { - var expr, token, prec, previousAllowIn, stack; - - previousAllowIn = state.allowIn; - state.allowIn = true; - - expr = parseUnaryExpression(); - - token = lookahead; - prec = binaryPrecedence(token, previousAllowIn); - if (prec === 0) { - return expr; - } - token.prec = prec; - lex(); - - stack = [expr, token, parseUnaryExpression()]; - - while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { - - // Reduce. - while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { - reduceBinary(stack); - } - - // Shift. - token = lex(); - token.prec = prec; - stack.push(token); - stack.push(parseUnaryExpression()); - } - - // Final reduce to clean-up the stack. - while (stack.length > 1) { - reduceBinary(stack); - } - - state.allowIn = previousAllowIn; - return stack[0]; - } - - - // 11.12 Conditional Operator - - function parseConditionalExpression() { - var expr, previousAllowIn, consequent, alternate; - - expr = parseBinaryExpression(); - - if (match('?')) { - lex(); - previousAllowIn = state.allowIn; - state.allowIn = true; - consequent = parseAssignmentExpression(); - state.allowIn = previousAllowIn; - expect(':'); - alternate = parseAssignmentExpression(); - - expr = delegate.createConditionalExpression(expr, consequent, alternate); - } - - return expr; - } - - // 11.13 Assignment Operators - - function parseAssignmentExpression() { - var token, left, right; - - token = lookahead; - left = parseConditionalExpression(); - - if (matchAssign()) { - // LeftHandSideExpression - if (!isLeftHandSide(left)) { - throwError({}, Messages.InvalidLHSInAssignment); - } - - // 11.13.1 - if (strict && left.type === Syntax.Identifier && isRestrictedWord(left.name)) { - throwErrorTolerant(token, Messages.StrictLHSAssignment); - } - - token = lex(); - right = parseAssignmentExpression(); - return delegate.createAssignmentExpression(token.value, left, right); - } - - return left; - } - - // 11.14 Comma Operator - - function parseExpression() { - var expr = parseAssignmentExpression(); - - if (match(',')) { - expr = delegate.createSequenceExpression([ expr ]); - - while (index < length) { - if (!match(',')) { - break; - } - lex(); - expr.expressions.push(parseAssignmentExpression()); - } - - } - return expr; - } - - // 12.1 Block - - function parseStatementList() { - var list = [], - statement; - - while (index < length) { - if (match('}')) { - break; - } - statement = parseSourceElement(); - if (typeof statement === 'undefined') { - break; - } - list.push(statement); - } - - return list; - } - - function parseBlock() { - var block; - - expect('{'); - - block = parseStatementList(); - - expect('}'); - - return delegate.createBlockStatement(block); - } - - // 12.2 Variable Statement - - function parseVariableIdentifier() { - var token = lex(); - - if (token.type !== Token.Identifier) { - throwUnexpected(token); - } - - return delegate.createIdentifier(token.value); - } - - function parseVariableDeclaration(kind) { - var id = parseVariableIdentifier(), - init = null; - - // 12.2.1 - if (strict && isRestrictedWord(id.name)) { - throwErrorTolerant({}, Messages.StrictVarName); - } - - if (kind === 'const') { - expect('='); - init = parseAssignmentExpression(); - } else if (match('=')) { - lex(); - init = parseAssignmentExpression(); - } - - return delegate.createVariableDeclarator(id, init); - } - - function parseVariableDeclarationList(kind) { - var list = []; - - while (index < length) { - list.push(parseVariableDeclaration(kind)); - if (!match(',')) { - break; - } - lex(); - } - - return list; - } - - function parseVariableStatement() { - var declarations; - - expectKeyword('var'); - - declarations = parseVariableDeclarationList(); - - consumeSemicolon(); - - return delegate.createVariableDeclaration(declarations, 'var'); - } - - // kind may be `const` or `let` - // Both are experimental and not in the specification yet. - // see http://wiki.ecmascript.org/doku.php?id=harmony:const - // and http://wiki.ecmascript.org/doku.php?id=harmony:let - function parseConstLetDeclaration(kind) { - var declarations; - - expectKeyword(kind); - - declarations = parseVariableDeclarationList(kind); - - consumeSemicolon(); - - return delegate.createVariableDeclaration(declarations, kind); - } - - // 12.3 Empty Statement - - function parseEmptyStatement() { - expect(';'); - return delegate.createEmptyStatement(); - } - - // 12.4 Expression Statement - - function parseExpressionStatement() { - var expr = parseExpression(); - consumeSemicolon(); - return delegate.createExpressionStatement(expr); - } - - // 12.5 If statement - - function parseIfStatement() { - var test, consequent, alternate; - - expectKeyword('if'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - consequent = parseStatement(); - - if (matchKeyword('else')) { - lex(); - alternate = parseStatement(); - } else { - alternate = null; - } - - return delegate.createIfStatement(test, consequent, alternate); - } - - // 12.6 Iteration Statements - - function parseDoWhileStatement() { - var body, test, oldInIteration; - - expectKeyword('do'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - expectKeyword('while'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - if (match(';')) { - lex(); - } - - return delegate.createDoWhileStatement(body, test); - } - - function parseWhileStatement() { - var test, body, oldInIteration; - - expectKeyword('while'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - return delegate.createWhileStatement(test, body); - } - - function parseForVariableDeclaration() { - var token = lex(), - declarations = parseVariableDeclarationList(); - - return delegate.createVariableDeclaration(declarations, token.value); - } - - function parseForStatement() { - var init, test, update, left, right, body, oldInIteration; - - init = test = update = null; - - expectKeyword('for'); - - expect('('); - - if (match(';')) { - lex(); - } else { - if (matchKeyword('var') || matchKeyword('let')) { - state.allowIn = false; - init = parseForVariableDeclaration(); - state.allowIn = true; - - if (init.declarations.length === 1 && matchKeyword('in')) { - lex(); - left = init; - right = parseExpression(); - init = null; - } - } else { - state.allowIn = false; - init = parseExpression(); - state.allowIn = true; - - if (matchKeyword('in')) { - // LeftHandSideExpression - if (!isLeftHandSide(init)) { - throwError({}, Messages.InvalidLHSInForIn); - } - - lex(); - left = init; - right = parseExpression(); - init = null; - } - } - - if (typeof left === 'undefined') { - expect(';'); - } - } - - if (typeof left === 'undefined') { - - if (!match(';')) { - test = parseExpression(); - } - expect(';'); - - if (!match(')')) { - update = parseExpression(); - } - } - - expect(')'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - return (typeof left === 'undefined') ? - delegate.createForStatement(init, test, update, body) : - delegate.createForInStatement(left, right, body); - } - - // 12.7 The continue statement - - function parseContinueStatement() { - var label = null; - - expectKeyword('continue'); - - // Optimize the most common form: 'continue;'. - if (source.charCodeAt(index) === 59) { - lex(); - - if (!state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return delegate.createContinueStatement(null); - } - - if (peekLineTerminator()) { - if (!state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return delegate.createContinueStatement(null); - } - - if (lookahead.type === Token.Identifier) { - label = parseVariableIdentifier(); - - if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { - throwError({}, Messages.UnknownLabel, label.name); - } - } - - consumeSemicolon(); - - if (label === null && !state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return delegate.createContinueStatement(label); - } - - // 12.8 The break statement - - function parseBreakStatement() { - var label = null; - - expectKeyword('break'); - - // Catch the very common case first: immediately a semicolon (char #59). - if (source.charCodeAt(index) === 59) { - lex(); - - if (!(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return delegate.createBreakStatement(null); - } - - if (peekLineTerminator()) { - if (!(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return delegate.createBreakStatement(null); - } - - if (lookahead.type === Token.Identifier) { - label = parseVariableIdentifier(); - - if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { - throwError({}, Messages.UnknownLabel, label.name); - } - } - - consumeSemicolon(); - - if (label === null && !(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return delegate.createBreakStatement(label); - } - - // 12.9 The return statement - - function parseReturnStatement() { - var argument = null; - - expectKeyword('return'); - - if (!state.inFunctionBody) { - throwErrorTolerant({}, Messages.IllegalReturn); - } - - // 'return' followed by a space and an identifier is very common. - if (source.charCodeAt(index) === 32) { - if (isIdentifierStart(source.charCodeAt(index + 1))) { - argument = parseExpression(); - consumeSemicolon(); - return delegate.createReturnStatement(argument); - } - } - - if (peekLineTerminator()) { - return delegate.createReturnStatement(null); - } - - if (!match(';')) { - if (!match('}') && lookahead.type !== Token.EOF) { - argument = parseExpression(); - } - } - - consumeSemicolon(); - - return delegate.createReturnStatement(argument); - } - - // 12.10 The with statement - - function parseWithStatement() { - var object, body; - - if (strict) { - throwErrorTolerant({}, Messages.StrictModeWith); - } - - expectKeyword('with'); - - expect('('); - - object = parseExpression(); - - expect(')'); - - body = parseStatement(); - - return delegate.createWithStatement(object, body); - } - - // 12.10 The swith statement - - function parseSwitchCase() { - var test, - consequent = [], - statement; - - if (matchKeyword('default')) { - lex(); - test = null; - } else { - expectKeyword('case'); - test = parseExpression(); - } - expect(':'); - - while (index < length) { - if (match('}') || matchKeyword('default') || matchKeyword('case')) { - break; - } - statement = parseStatement(); - if (typeof statement === 'undefined') { - break; - } - consequent.push(statement); - } - - return delegate.createSwitchCase(test, consequent); - } - - function parseSwitchStatement() { - var discriminant, cases, clause, oldInSwitch, defaultFound; - - expectKeyword('switch'); - - expect('('); - - discriminant = parseExpression(); - - expect(')'); - - expect('{'); - - if (match('}')) { - lex(); - return delegate.createSwitchStatement(discriminant); - } - - cases = []; - - oldInSwitch = state.inSwitch; - state.inSwitch = true; - defaultFound = false; - - while (index < length) { - if (match('}')) { - break; - } - clause = parseSwitchCase(); - if (clause.test === null) { - if (defaultFound) { - throwError({}, Messages.MultipleDefaultsInSwitch); - } - defaultFound = true; - } - cases.push(clause); - } - - state.inSwitch = oldInSwitch; - - expect('}'); - - return delegate.createSwitchStatement(discriminant, cases); - } - - // 12.13 The throw statement - - function parseThrowStatement() { - var argument; - - expectKeyword('throw'); - - if (peekLineTerminator()) { - throwError({}, Messages.NewlineAfterThrow); - } - - argument = parseExpression(); - - consumeSemicolon(); - - return delegate.createThrowStatement(argument); - } - - // 12.14 The try statement - - function parseCatchClause() { - var param, body; - - expectKeyword('catch'); - - expect('('); - if (!match(')')) { - param = parseExpression(); - // 12.14.1 - if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { - throwErrorTolerant({}, Messages.StrictCatchVariable); - } - } - expect(')'); - body = parseBlock(); - return delegate.createCatchClause(param, body); - } - - function parseTryStatement() { - var block, handlers = [], finalizer = null; - - expectKeyword('try'); - - block = parseBlock(); - - if (matchKeyword('catch')) { - handlers.push(parseCatchClause()); - } - - if (matchKeyword('finally')) { - lex(); - finalizer = parseBlock(); - } - - if (handlers.length === 0 && !finalizer) { - throwError({}, Messages.NoCatchOrFinally); - } - - return delegate.createTryStatement(block, [], handlers, finalizer); - } - - // 12.15 The debugger statement - - function parseDebuggerStatement() { - expectKeyword('debugger'); - - consumeSemicolon(); - - return delegate.createDebuggerStatement(); - } - - // 12 Statements - - function parseStatement() { - var type = lookahead.type, - expr, - labeledBody; - - if (type === Token.EOF) { - throwUnexpected(lookahead); - } - - if (type === Token.Punctuator) { - switch (lookahead.value) { - case ';': - return parseEmptyStatement(); - case '{': - return parseBlock(); - case '(': - return parseExpressionStatement(); - default: - break; - } - } - - if (type === Token.Keyword) { - switch (lookahead.value) { - case 'break': - return parseBreakStatement(); - case 'continue': - return parseContinueStatement(); - case 'debugger': - return parseDebuggerStatement(); - case 'do': - return parseDoWhileStatement(); - case 'for': - return parseForStatement(); - case 'function': - return parseFunctionDeclaration(); - case 'if': - return parseIfStatement(); - case 'return': - return parseReturnStatement(); - case 'switch': - return parseSwitchStatement(); - case 'throw': - return parseThrowStatement(); - case 'try': - return parseTryStatement(); - case 'var': - return parseVariableStatement(); - case 'while': - return parseWhileStatement(); - case 'with': - return parseWithStatement(); - default: - break; - } - } - - expr = parseExpression(); - - // 12.12 Labelled Statements - if ((expr.type === Syntax.Identifier) && match(':')) { - lex(); - - if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) { - throwError({}, Messages.Redeclaration, 'Label', expr.name); - } - - state.labelSet[expr.name] = true; - labeledBody = parseStatement(); - delete state.labelSet[expr.name]; - return delegate.createLabeledStatement(expr, labeledBody); - } - - consumeSemicolon(); - - return delegate.createExpressionStatement(expr); - } - - // 13 Function Definition - - function parseFunctionSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted, - oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody; - - expect('{'); - - while (index < length) { - if (lookahead.type !== Token.StringLiteral) { - break; - } - token = lookahead; - - sourceElement = parseSourceElement(); - sourceElements.push(sourceElement); - if (sourceElement.expression.type !== Syntax.Literal) { - // this is not directive - break; - } - directive = source.slice(token.range[0] + 1, token.range[1] - 1); - if (directive === 'use strict') { - strict = true; - if (firstRestricted) { - throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); - } - } else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - - oldLabelSet = state.labelSet; - oldInIteration = state.inIteration; - oldInSwitch = state.inSwitch; - oldInFunctionBody = state.inFunctionBody; - - state.labelSet = {}; - state.inIteration = false; - state.inSwitch = false; - state.inFunctionBody = true; - - while (index < length) { - if (match('}')) { - break; - } - sourceElement = parseSourceElement(); - if (typeof sourceElement === 'undefined') { - break; - } - sourceElements.push(sourceElement); - } - - expect('}'); - - state.labelSet = oldLabelSet; - state.inIteration = oldInIteration; - state.inSwitch = oldInSwitch; - state.inFunctionBody = oldInFunctionBody; - - return delegate.createBlockStatement(sourceElements); - } - - function parseParams(firstRestricted) { - var param, params = [], token, stricted, paramSet, message; - expect('('); - - if (!match(')')) { - paramSet = {}; - while (index < length) { - token = lookahead; - param = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - stricted = token; - message = Messages.StrictParamName; - } - if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - stricted = token; - message = Messages.StrictParamDupe; - } - } else if (!firstRestricted) { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictParamName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - firstRestricted = token; - message = Messages.StrictParamDupe; - } - } - params.push(param); - paramSet[param.name] = true; - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - return { - params: params, - stricted: stricted, - firstRestricted: firstRestricted, - message: message - }; - } - - function parseFunctionDeclaration() { - var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict; - - expectKeyword('function'); - token = lookahead; - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwErrorTolerant(token, Messages.StrictFunctionName); - } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } - } - - tmp = parseParams(firstRestricted); - params = tmp.params; - stricted = tmp.stricted; - firstRestricted = tmp.firstRestricted; - if (tmp.message) { - message = tmp.message; - } - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (strict && firstRestricted) { - throwError(firstRestricted, message); - } - if (strict && stricted) { - throwErrorTolerant(stricted, message); - } - strict = previousStrict; - - return delegate.createFunctionDeclaration(id, params, [], body); - } - - function parseFunctionExpression() { - var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict; - - expectKeyword('function'); - - if (!match('(')) { - token = lookahead; - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwErrorTolerant(token, Messages.StrictFunctionName); - } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } - } - } - - tmp = parseParams(firstRestricted); - params = tmp.params; - stricted = tmp.stricted; - firstRestricted = tmp.firstRestricted; - if (tmp.message) { - message = tmp.message; - } - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (strict && firstRestricted) { - throwError(firstRestricted, message); - } - if (strict && stricted) { - throwErrorTolerant(stricted, message); - } - strict = previousStrict; - - return delegate.createFunctionExpression(id, params, [], body); - } - - // 14 Program - - function parseSourceElement() { - if (lookahead.type === Token.Keyword) { - switch (lookahead.value) { - case 'const': - case 'let': - return parseConstLetDeclaration(lookahead.value); - case 'function': - return parseFunctionDeclaration(); - default: - return parseStatement(); - } - } - - if (lookahead.type !== Token.EOF) { - return parseStatement(); - } - } - - function parseSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted; - - while (index < length) { - token = lookahead; - if (token.type !== Token.StringLiteral) { - break; - } - - sourceElement = parseSourceElement(); - sourceElements.push(sourceElement); - if (sourceElement.expression.type !== Syntax.Literal) { - // this is not directive - break; - } - directive = source.slice(token.range[0] + 1, token.range[1] - 1); - if (directive === 'use strict') { - strict = true; - if (firstRestricted) { - throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); - } - } else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - - while (index < length) { - sourceElement = parseSourceElement(); - if (typeof sourceElement === 'undefined') { - break; - } - sourceElements.push(sourceElement); - } - return sourceElements; - } - - function parseProgram() { - var body; - strict = false; - peek(); - body = parseSourceElements(); - return delegate.createProgram(body); - } - - // The following functions are needed only when the option to preserve - // the comments is active. - - function addComment(type, value, start, end, loc) { - assert(typeof start === 'number', 'Comment must have valid position'); - - // Because the way the actual token is scanned, often the comments - // (if any) are skipped twice during the lexical analysis. - // Thus, we need to skip adding a comment if the comment array already - // handled it. - if (extra.comments.length > 0) { - if (extra.comments[extra.comments.length - 1].range[1] > start) { - return; - } - } - - extra.comments.push({ - type: type, - value: value, - range: [start, end], - loc: loc - }); - } - - function scanComment() { - var comment, ch, loc, start, blockComment, lineComment; - - comment = ''; - blockComment = false; - lineComment = false; - - while (index < length) { - ch = source[index]; - - if (lineComment) { - ch = source[index++]; - if (isLineTerminator(ch.charCodeAt(0))) { - loc.end = { - line: lineNumber, - column: index - lineStart - 1 - }; - lineComment = false; - addComment('Line', comment, start, index - 1, loc); - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - comment = ''; - } else if (index >= length) { - lineComment = false; - comment += ch; - loc.end = { - line: lineNumber, - column: length - lineStart - }; - addComment('Line', comment, start, length, loc); - } else { - comment += ch; - } - } else if (blockComment) { - if (isLineTerminator(ch.charCodeAt(0))) { - if (ch === '\r' && source[index + 1] === '\n') { - ++index; - comment += '\r\n'; - } else { - comment += ch; - } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - ch = source[index++]; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - comment += ch; - if (ch === '*') { - ch = source[index]; - if (ch === '/') { - comment = comment.substr(0, comment.length - 1); - blockComment = false; - ++index; - loc.end = { - line: lineNumber, - column: index - lineStart - }; - addComment('Block', comment, start, index, loc); - comment = ''; - } - } - } - } else if (ch === '/') { - ch = source[index + 1]; - if (ch === '/') { - loc = { - start: { - line: lineNumber, - column: index - lineStart - } - }; - start = index; - index += 2; - lineComment = true; - if (index >= length) { - loc.end = { - line: lineNumber, - column: index - lineStart - }; - lineComment = false; - addComment('Line', comment, start, index, loc); - } - } else if (ch === '*') { - start = index; - index += 2; - blockComment = true; - loc = { - start: { - line: lineNumber, - column: index - lineStart - 2 - } - }; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - break; - } - } else if (isWhiteSpace(ch.charCodeAt(0))) { - ++index; - } else if (isLineTerminator(ch.charCodeAt(0))) { - ++index; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - } else { - break; - } - } - } - - function filterCommentLocation() { - var i, entry, comment, comments = []; - - for (i = 0; i < extra.comments.length; ++i) { - entry = extra.comments[i]; - comment = { - type: entry.type, - value: entry.value - }; - if (extra.range) { - comment.range = entry.range; - } - if (extra.loc) { - comment.loc = entry.loc; - } - comments.push(comment); - } - - extra.comments = comments; - } - - function collectToken() { - var start, loc, token, range, value; - - skipComment(); - start = index; - loc = { - start: { - line: lineNumber, - column: index - lineStart - } - }; - - token = extra.advance(); - loc.end = { - line: lineNumber, - column: index - lineStart - }; - - if (token.type !== Token.EOF) { - range = [token.range[0], token.range[1]]; - value = source.slice(token.range[0], token.range[1]); - extra.tokens.push({ - type: TokenName[token.type], - value: value, - range: range, - loc: loc - }); - } - - return token; - } - - function collectRegex() { - var pos, loc, regex, token; - - skipComment(); - - pos = index; - loc = { - start: { - line: lineNumber, - column: index - lineStart - } - }; - - regex = extra.scanRegExp(); - loc.end = { - line: lineNumber, - column: index - lineStart - }; - - // Pop the previous token, which is likely '/' or '/=' - if (extra.tokens.length > 0) { - token = extra.tokens[extra.tokens.length - 1]; - if (token.range[0] === pos && token.type === 'Punctuator') { - if (token.value === '/' || token.value === '/=') { - extra.tokens.pop(); - } - } - } - - extra.tokens.push({ - type: 'RegularExpression', - value: regex.literal, - range: [pos, index], - loc: loc - }); - - return regex; - } - - function filterTokenLocation() { - var i, entry, token, tokens = []; - - for (i = 0; i < extra.tokens.length; ++i) { - entry = extra.tokens[i]; - token = { - type: entry.type, - value: entry.value - }; - if (extra.range) { - token.range = entry.range; - } - if (extra.loc) { - token.loc = entry.loc; - } - tokens.push(token); - } - - extra.tokens = tokens; - } - - function createLocationMarker() { - var marker = {}; - - marker.range = [index, index]; - marker.loc = { - start: { - line: lineNumber, - column: index - lineStart - }, - end: { - line: lineNumber, - column: index - lineStart - } - }; - - marker.end = function () { - this.range[1] = index; - this.loc.end.line = lineNumber; - this.loc.end.column = index - lineStart; - }; - - marker.applyGroup = function (node) { - if (extra.range) { - node.groupRange = [this.range[0], this.range[1]]; - } - if (extra.loc) { - node.groupLoc = { - start: { - line: this.loc.start.line, - column: this.loc.start.column - }, - end: { - line: this.loc.end.line, - column: this.loc.end.column - } - }; - } - }; - - marker.apply = function (node) { - if (extra.range) { - node.range = [this.range[0], this.range[1]]; - } - if (extra.loc) { - node.loc = { - start: { - line: this.loc.start.line, - column: this.loc.start.column - }, - end: { - line: this.loc.end.line, - column: this.loc.end.column - } - }; - } - }; - - return marker; - } - - function trackGroupExpression() { - var marker, expr; - - skipComment(); - marker = createLocationMarker(); - expect('('); - - expr = parseExpression(); - - expect(')'); - - marker.end(); - marker.applyGroup(expr); - - return expr; - } - - function trackLeftHandSideExpression() { - var marker, expr, property; - - skipComment(); - marker = createLocationMarker(); - - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - - while (match('.') || match('[')) { - if (match('[')) { - property = parseComputedMember(); - expr = delegate.createMemberExpression('[', expr, property); - marker.end(); - marker.apply(expr); - } else { - property = parseNonComputedMember(); - expr = delegate.createMemberExpression('.', expr, property); - marker.end(); - marker.apply(expr); - } - } - - return expr; - } - - function trackLeftHandSideExpressionAllowCall() { - var marker, expr, args, property; - - skipComment(); - marker = createLocationMarker(); - - expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - - while (match('.') || match('[') || match('(')) { - if (match('(')) { - args = parseArguments(); - expr = delegate.createCallExpression(expr, args); - marker.end(); - marker.apply(expr); - } else if (match('[')) { - property = parseComputedMember(); - expr = delegate.createMemberExpression('[', expr, property); - marker.end(); - marker.apply(expr); - } else { - property = parseNonComputedMember(); - expr = delegate.createMemberExpression('.', expr, property); - marker.end(); - marker.apply(expr); - } - } - - return expr; - } - - function filterGroup(node) { - var n, i, entry; - - n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; - for (i in node) { - if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { - entry = node[i]; - if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { - n[i] = entry; - } else { - n[i] = filterGroup(entry); - } - } - } - return n; - } - - function wrapTrackingFunction(range, loc) { - - return function (parseFunction) { - - function isBinary(node) { - return node.type === Syntax.LogicalExpression || - node.type === Syntax.BinaryExpression; - } - - function visit(node) { - var start, end; - - if (isBinary(node.left)) { - visit(node.left); - } - if (isBinary(node.right)) { - visit(node.right); - } - - if (range) { - if (node.left.groupRange || node.right.groupRange) { - start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; - end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; - node.range = [start, end]; - } else if (typeof node.range === 'undefined') { - start = node.left.range[0]; - end = node.right.range[1]; - node.range = [start, end]; - } - } - if (loc) { - if (node.left.groupLoc || node.right.groupLoc) { - start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; - end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; - node.loc = { - start: start, - end: end - }; - } else if (typeof node.loc === 'undefined') { - node.loc = { - start: node.left.loc.start, - end: node.right.loc.end - }; - } - } - } - - return function () { - var marker, node; - - skipComment(); - - marker = createLocationMarker(); - node = parseFunction.apply(null, arguments); - marker.end(); - - if (range && typeof node.range === 'undefined') { - marker.apply(node); - } - - if (loc && typeof node.loc === 'undefined') { - marker.apply(node); - } - - if (isBinary(node)) { - visit(node); - } - - return node; - }; - }; - } - - function patch() { - - var wrapTracking; - - if (extra.comments) { - extra.skipComment = skipComment; - skipComment = scanComment; - } - - if (extra.range || extra.loc) { - - extra.parseGroupExpression = parseGroupExpression; - extra.parseLeftHandSideExpression = parseLeftHandSideExpression; - extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; - parseGroupExpression = trackGroupExpression; - parseLeftHandSideExpression = trackLeftHandSideExpression; - parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; - - wrapTracking = wrapTrackingFunction(extra.range, extra.loc); - - extra.parseAssignmentExpression = parseAssignmentExpression; - extra.parseBinaryExpression = parseBinaryExpression; - extra.parseBlock = parseBlock; - extra.parseFunctionSourceElements = parseFunctionSourceElements; - extra.parseCatchClause = parseCatchClause; - extra.parseComputedMember = parseComputedMember; - extra.parseConditionalExpression = parseConditionalExpression; - extra.parseConstLetDeclaration = parseConstLetDeclaration; - extra.parseExpression = parseExpression; - extra.parseForVariableDeclaration = parseForVariableDeclaration; - extra.parseFunctionDeclaration = parseFunctionDeclaration; - extra.parseFunctionExpression = parseFunctionExpression; - extra.parseNewExpression = parseNewExpression; - extra.parseNonComputedProperty = parseNonComputedProperty; - extra.parseObjectProperty = parseObjectProperty; - extra.parseObjectPropertyKey = parseObjectPropertyKey; - extra.parsePostfixExpression = parsePostfixExpression; - extra.parsePrimaryExpression = parsePrimaryExpression; - extra.parseProgram = parseProgram; - extra.parsePropertyFunction = parsePropertyFunction; - extra.parseStatement = parseStatement; - extra.parseSwitchCase = parseSwitchCase; - extra.parseUnaryExpression = parseUnaryExpression; - extra.parseVariableDeclaration = parseVariableDeclaration; - extra.parseVariableIdentifier = parseVariableIdentifier; - - parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); - parseBinaryExpression = wrapTracking(extra.parseBinaryExpression); - parseBlock = wrapTracking(extra.parseBlock); - parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); - parseCatchClause = wrapTracking(extra.parseCatchClause); - parseComputedMember = wrapTracking(extra.parseComputedMember); - parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); - parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); - parseExpression = wrapTracking(extra.parseExpression); - parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); - parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); - parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); - parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); - parseNewExpression = wrapTracking(extra.parseNewExpression); - parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); - parseObjectProperty = wrapTracking(extra.parseObjectProperty); - parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); - parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); - parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); - parseProgram = wrapTracking(extra.parseProgram); - parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); - parseStatement = wrapTracking(extra.parseStatement); - parseSwitchCase = wrapTracking(extra.parseSwitchCase); - parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); - parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); - parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); - } - - if (typeof extra.tokens !== 'undefined') { - extra.advance = advance; - extra.scanRegExp = scanRegExp; - - advance = collectToken; - scanRegExp = collectRegex; - } - } - - function unpatch() { - if (typeof extra.skipComment === 'function') { - skipComment = extra.skipComment; - } - - if (extra.range || extra.loc) { - parseAssignmentExpression = extra.parseAssignmentExpression; - parseBinaryExpression = extra.parseBinaryExpression; - parseBlock = extra.parseBlock; - parseFunctionSourceElements = extra.parseFunctionSourceElements; - parseCatchClause = extra.parseCatchClause; - parseComputedMember = extra.parseComputedMember; - parseConditionalExpression = extra.parseConditionalExpression; - parseConstLetDeclaration = extra.parseConstLetDeclaration; - parseExpression = extra.parseExpression; - parseForVariableDeclaration = extra.parseForVariableDeclaration; - parseFunctionDeclaration = extra.parseFunctionDeclaration; - parseFunctionExpression = extra.parseFunctionExpression; - parseGroupExpression = extra.parseGroupExpression; - parseLeftHandSideExpression = extra.parseLeftHandSideExpression; - parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; - parseNewExpression = extra.parseNewExpression; - parseNonComputedProperty = extra.parseNonComputedProperty; - parseObjectProperty = extra.parseObjectProperty; - parseObjectPropertyKey = extra.parseObjectPropertyKey; - parsePrimaryExpression = extra.parsePrimaryExpression; - parsePostfixExpression = extra.parsePostfixExpression; - parseProgram = extra.parseProgram; - parsePropertyFunction = extra.parsePropertyFunction; - parseStatement = extra.parseStatement; - parseSwitchCase = extra.parseSwitchCase; - parseUnaryExpression = extra.parseUnaryExpression; - parseVariableDeclaration = extra.parseVariableDeclaration; - parseVariableIdentifier = extra.parseVariableIdentifier; - } - - if (typeof extra.scanRegExp === 'function') { - advance = extra.advance; - scanRegExp = extra.scanRegExp; - } - } - - // This is used to modify the delegate. - - function extend(object, properties) { - var entry, result = {}; - - for (entry in object) { - if (object.hasOwnProperty(entry)) { - result[entry] = object[entry]; - } - } - - for (entry in properties) { - if (properties.hasOwnProperty(entry)) { - result[entry] = properties[entry]; - } - } - - return result; - } - - function parse(code, options) { - var program, toString; - - toString = String; - if (typeof code !== 'string' && !(code instanceof String)) { - code = toString(code); - } - - delegate = SyntaxTreeDelegate; - source = code; - index = 0; - lineNumber = (source.length > 0) ? 1 : 0; - lineStart = 0; - length = source.length; - lookahead = null; - state = { - allowIn: true, - labelSet: {}, - inFunctionBody: false, - inIteration: false, - inSwitch: false - }; - - extra = {}; - if (typeof options !== 'undefined') { - extra.range = (typeof options.range === 'boolean') && options.range; - extra.loc = (typeof options.loc === 'boolean') && options.loc; - - if (typeof options.tokens === 'boolean' && options.tokens) { - extra.tokens = []; - } - if (typeof options.comment === 'boolean' && options.comment) { - extra.comments = []; - } - if (typeof options.tolerant === 'boolean' && options.tolerant) { - extra.errors = []; - } - } - - if (length > 0) { - if (typeof source[0] === 'undefined') { - // Try first to convert to a string. This is good as fast path - // for old IE which understands string indexing for string - // literals only and not for string object. - if (code instanceof String) { - source = code.valueOf(); - } - } - } - - patch(); - try { - program = parseProgram(); - if (typeof extra.comments !== 'undefined') { - filterCommentLocation(); - program.comments = extra.comments; - } - if (typeof extra.tokens !== 'undefined') { - filterTokenLocation(); - program.tokens = extra.tokens; - } - if (typeof extra.errors !== 'undefined') { - program.errors = extra.errors; - } - if (extra.range || extra.loc) { - program.body = filterGroup(program.body); - } - } catch (e) { - throw e; - } finally { - unpatch(); - extra = {}; - } - - return program; - } - - // Sync with package.json and component.json. - exports.version = '1.1.0-dev'; - - exports.parse = parse; - - // Deep copy. - exports.Syntax = (function () { - var name, types = {}; - - if (typeof Object.create === 'function') { - types = Object.create(null); - } - - for (name in Syntax) { - if (Syntax.hasOwnProperty(name)) { - types[name] = Syntax[name]; - } - } - - if (typeof Object.freeze === 'function') { - Object.freeze(types); - } - - return types; - }()); - -})); -/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/coverage_store.js b/coverage_store.js deleted file mode 100644 index 5ee6f6b..0000000 --- a/coverage_store.js +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2011 Itay Neeman -// -// Licensed under the MIT License - -(function() { - var coverageStore = {}; - - module.exports = {}; - module.exports.register = function(filename) { - var store = coverageStore[filename] = coverageStore[filename] || {nodes: {}, blocks: {}}; - - return store; - } - - module.exports.getStore = function(filename) { - return coverageStore[filename] || {}; - } -})(); \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..1c7f4d0 --- /dev/null +++ b/index.html @@ -0,0 +1,88 @@ + + + + + + itay/node-cover @ GitHub + + + + + + Fork me on GitHub + +
+ +
+ + + + +
+ +

node-cover + by itay

+ +
+ Native JavaScript Code Coverage +
+ + + + + + + + + + +

Authors

+

Itay Neeman (itay@neeman.net)

+ + + +

Contact

+

Itay Neeman (itay@neeman.net)

+ + +

Download

+

+ You can download this project in either + zip or + tar formats. +

+

You can also clone the project with Git + by running: +

$ git clone git://github.com/itay/node-cover
+

+ + + +
+ + + diff --git a/index.js b/index.js deleted file mode 100644 index 7eefadd..0000000 --- a/index.js +++ /dev/null @@ -1,440 +0,0 @@ -var instrument = require('./instrument') -var Module = require('module').Module; -var path = require('path'); -var fs = require('fs'); -var vm = require('vm'); -var _ = require('underscore'); - -// Coverage tracker -function CoverageData (filename, instrumentor) { - this.instrumentor = instrumentor; - this.filename = filename; - this.nodes = {}; - this.visitedBlocks = {}; - this.source = instrumentor.source; -}; - -// Note that a node has been visited -CoverageData.prototype.visit = function(node) { - var node = this.nodes[node.id] = (this.nodes[node.id] || {node:node, count:0}) - node.count++; -}; - -// Note that a node has been visited -CoverageData.prototype.visitBlock = function(blockIndex) { - var block = this.visitedBlocks[blockIndex] = (this.visitedBlocks[blockIndex] || {count:0}) - block.count++; -}; - -// Get all the nodes we did not see -CoverageData.prototype.missing = function() { - // Find all the nodes which we haven't seen - var nodes = this.nodes; - var missing = this.instrumentor.filter(function(node) { - return !nodes[node.id]; - }); - - return missing; -}; - -// Get all the nodes we did see -CoverageData.prototype.seen = function() { - // Find all the nodes we have seen - var nodes = this.nodes; - var seen = this.instrumentor.filter(function(node) { - return !!nodes[node.id]; - }); - - return seen; -}; - -// Calculate node coverage statistics -CoverageData.prototype.blocks = function() { - var totalBlocks = this.instrumentor.blockCounter; - var numSeenBlocks = 0; - for(var index in this.visitedBlocks) { - numSeenBlocks++; - } - var numMissingBlocks = totalBlocks - numSeenBlocks; - - var toReturn = { - total: totalBlocks, - seen: numSeenBlocks, - missing: numMissingBlocks, - percentage: totalBlocks ? numSeenBlocks / totalBlocks : 1 - }; - - return toReturn; -}; - -// Explode all multi-line nodes into single-line ones. -var explodeNodes = function(coverageData, fileData) { - var missing = coverageData.missing(); - var newNodes = []; - - // Get only the multi-line nodes. - var multiLineNodes = missing.filter(function(node) { - return (node.loc.start.line < node.loc.end.line); - }); - - for(var i = 0; i < multiLineNodes.length; i++) { - // Get the current node and delta - var node = multiLineNodes[i]; - var lineDelta = node.loc.end.line - node.loc.start.line + 1; - - for(var j = 0; j < lineDelta; j++) { - // For each line in the multi-line node, we'll create a - // new node, and we set the start and end columns - // to the correct vlaues. - var curLine = node.loc.start.line + j; - var startCol = 0; - var endCol = fileData[curLine - 1].length; - - if (curLine === node.loc.start.line) { - startCol = node.loc.start.column; - } - else if (curLine === node.loc.end.line) { - startCol = 0; - endCol = node.loc.end.column; - } - - var newNode = { - loc: - { - start: { - line: curLine, - col: startCol - }, - end: { - line: curLine, - col: endCol - } - } - }; - - newNodes.push(newNode); - } - } - - return newNodes; -} - -// Get per-line code coverage information -CoverageData.prototype.coverage = function() { - var missingLines = this.missing(); - var fileData = this.instrumentor.source.split('\n'); - - // Get a dictionary of all the lines we did observe being at least - // partially covered - var seen = {}; - - this.seen().forEach(function(node) { - seen[node.loc.start.line] = true; - }); - - // Add all the new multi-line nodes. - missingLines = missingLines.concat(explodeNodes(this, fileData)); - - var seenNodes = {}; - missingLines = missingLines.sort( - function(lhs, rhs) { - var lhsNode = lhs.loc; - var rhsNode = rhs.loc; - - // First try to sort based on line - return lhsNode.start.line < rhsNode.start.line ? -1 : // first try line - lhsNode.start.line > rhsNode.start.line ? 1 : - lhsNode.start.column < rhsNode.start.column ? -1 : // then try start col - lhsNode.start.column > rhsNode.start.column ? 1 : - lhsNode.end.column < rhsNode.end.column ? -1 : // then try end col - lhsNode.end.column > rhsNode.end.column ? 1 : - 0; // then just give up and say they are equal - }).filter(function(node) { - // If it is a multi-line node, we can just ignore it - if (node.loc.start.line < node.loc.end.line) { - return false; - } - - // We allow multiple nodes per line, but only one node per - // start column (due to how instrumented works) - var okay = false; - if (seenNodes.hasOwnProperty(node.loc.start.line)) { - var isNew = (seenNodes[node.loc.start.line].indexOf(node.loc.start.column) < 0); - if (isNew) { - seenNodes[node.loc.start.line].push(node.loc.start.column); - okay = true; - } - } - else { - seenNodes[node.loc.start.line] = [node.loc.start.column]; - okay = true; - } - - return okay; - }); - - var coverage = {}; - - missingLines.forEach(function(node) { - // For each missing line, add some information for it - var line = node.loc.start.line; - var startCol = node.loc.start.column; - var endCol = node.loc.end.column; - var source = fileData[line - 1]; - var partial = seen.hasOwnProperty(line) && seen[line]; - - if (coverage.hasOwnProperty(line)) { - coverage[line].missing.push({startCol: startCol, endCol: endCol}); - } - else { - coverage[line] = { - partial: partial, - source: source, - missing: [{startCol: startCol, endCol: endCol}] - }; - } - }); - - return coverage; -}; - -CoverageData.prototype.prepare = function() { - var store = require('./coverage_store').getStore(this.filename); - - for(var index in store.nodes) { - if (store.nodes.hasOwnProperty(index)) { - this.nodes[index] = {node: this.instrumentor.nodes[index], count: store.nodes[index].count}; - } - } - - for(var index in store.blocks) { - if (store.blocks.hasOwnProperty(index)) { - this.visitedBlocks[index] = {count: store.blocks[index].count}; - } - } -}; - -// Get statistics for the entire file, including per-line code coverage -// and block-level coverage -CoverageData.prototype.stats = function() { - this.prepare(); - - var missing = this.missing(); - var filedata = this.instrumentor.source.split('\n'); - - var observedMissing = []; - var linesInfo = missing.sort(function(lhs, rhs) { - return lhs.loc.start.line < rhs.loc.start.line ? -1 : - lhs.loc.start.line > rhs.loc.start.line ? 1 : - 0; - }).filter(function(node) { - // Make sure we don't double count missing lines due to multi-line - // issues - var okay = (observedMissing.indexOf(node.loc.start.line) < 0); - if(okay) { - observedMissing.push(node.loc.start.line); - } - - return okay; - }).map(function(node, idx, all) { - // For each missing line, add info for it - return { - lineno: node.loc.start.line, - source: function() { return filedata[node.loc.start.line - 1]; } - }; - }); - - var numLines = filedata.length; - var numMissingLines = observedMissing.length; - var numSeenLines = numLines - numMissingLines; - var percentageCovered = numSeenLines / numLines; - - return { - percentage: percentageCovered, - lines: linesInfo, - missing: numMissingLines, - seen: numSeenLines, - total: numLines, - coverage: this.coverage(), - source: this.source, - blocks: this.blocks() - }; -}; - -// Require the CLI module of cover and return it, -// in case anyone wants to use it programmatically -var cli = function() { - return require('./bin/cover'); -}; - -var addInstrumentationHeader = function(template, filename, instrumented, coverageStorePath) { - var template = _.template(template); - var renderedSource = template({ - instrumented: instrumented, - coverageStorePath: coverageStorePath, - filename: filename, - source: instrumented.instrumentedSource - }); - - return renderedSource -}; - -var stripBOM = function(content) { - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - // because the buffer-to-string conversion in `fs.readFileSync()` - // translates it to FEFF, the UTF-16 BOM. - if (content.charCodeAt(0) === 0xFEFF) { - content = content.slice(1); - } - return content; -} - -var load = function(datas) { - var combinedCoverage = {}; - - _.each(datas, function(data) { - _.each(data.files, function(fileData, filename) { - var instrumentor = { - source: fileData.instrumentor.source, - nodes: fileData.instrumentor.nodes, - nodeCounter: fileData.instrumentor.nodeCounter, - blockCounter: fileData.instrumentor.blockCounter, - }; - - var coverage = new CoverageData(filename, new instrument.Instrumentor()); - coverage.instrumentor.source = fileData.instrumentor.source; - coverage.instrumentor.nodes = fileData.instrumentor.nodes; - coverage.instrumentor.nodeCounter = fileData.instrumentor.nodeCounter; - coverage.instrumentor.blockCounter = fileData.instrumentor.blockCounter; - - coverage.source = coverage.instrumentor.source; - coverage.hash = fileData.hash; - coverage.nodes = fileData.nodes; - coverage.visitedBlocks = fileData.blocks; - - if (combinedCoverage.hasOwnProperty(filename)) { - var coverageSoFar = combinedCoverage[filename]; - - if (coverageSoFar.hash !== coverage.hash) { - throw new Error("Multiple versions of file '" + filename + "' in coverage data!"); - } - - // Merge nodes - _.each(coverage.nodes, function(nodeData, index) { - var nodeDataSoFar = coverageSoFar.nodes[index] = (coverageSoFar.nodes[index] || {node: nodeData.node, count: 0}); - nodeDataSoFar.count += nodeData.count; - }); - - // Merge blocks - _.each(coverage.visitedBlocks, function(blockData, index) { - var blockDataSoFar = coverageSoFar.visitedBlocks[index] = (coverageSoFar.visitedBlocks[index] || {count: 0}); - blockDataSoFar.count += blockData.count; - }); - } - else { - combinedCoverage[filename] = coverage; - } - }); - }); - - return combinedCoverage; -} - -var cover = function(fileRegex, ignore, debugDirectory) { - var originalRequire = require.extensions['.js']; - var coverageData = {}; - var match = null; - - ignore = ignore || {}; - - if (fileRegex instanceof RegExp) { - match = regex; - } - else { - match = new RegExp(fileRegex ? (fileRegex.replace(/\//g, '\\/').replace(/\./g, '\\.')) : ".*", ''); - } - - var pathToCoverageStore = path.resolve(path.resolve(__dirname), "coverage_store.js").replace(/\\/g, "/"); - var templatePath = path.resolve(path.resolve(__dirname), "templates", "instrumentation_header.js"); - var template = fs.readFileSync(templatePath, 'utf-8'); - - require.extensions['.js'] = function(module, filename) { - - filename = filename.replace(/\\/g, "/"); - - if(!match.test(filename)) return originalRequire(module, filename); - if(filename === pathToCoverageStore) return originalRequire(module, filename); - - // If the specific file is to be ignored - var full = path.resolve(filename); - if(ignore[full]) { - return originalRequire(module, filename); - } - - // If any of the parents of the file are to be ignored - do { - full = path.dirname(full); - if (ignore[full]) { - return originalRequire(module, filename); - } - } while(full !== path.dirname(full)); - - var data = stripBOM(fs.readFileSync(filename, 'utf8').trim()); - data = data.replace(/^\#\!.*/, ''); - - var instrumented = instrument(data); - var coverage = coverageData[filename] = new CoverageData(filename, instrumented); - - var newCode = addInstrumentationHeader(template, filename, instrumented, pathToCoverageStore); - - if (debugDirectory) { - var outputPath = path.join(debugDirectory, filename.replace(/[\/|\:|\\]/g, "_") + ".js"); - fs.writeFileSync(outputPath, newCode); - } - - return module._compile(newCode, filename); - }; - - // Setup the data retrieval and release functions - var coverage = function(ready) { - ready(coverageData); - }; - - coverage.release = function() { - require.extensions['.js'] = originalRequire; - }; - - return coverage; -}; - -module.exports = { - cover: cover, - cli: cli, - load: load, - hook: function() { - var c = cli(); - c.hook.apply(c, arguments); - }, - combine: function() { - var c = cli(); - c.combine.apply(c, arguments); - }, - hookAndReport: function() { - var c = cli(); - c.hookAndReport.apply(c, arguments); - }, - hookAndCombine: function() { - var c = cli(); - c.hookAndCombine.apply(c, arguments); - }, - hookAndCombineAndReport: function() { - var c = cli(); - c.hookAndCombineAndReport.apply(c, arguments); - }, - reporters: { - html: require('./reporters/html'), - plain: require('./reporters/plain'), - cli: require('./reporters/cli'), - json: require('./reporters/json') - } -}; \ No newline at end of file diff --git a/instrument.js b/instrument.js deleted file mode 100644 index 6ebd4d2..0000000 --- a/instrument.js +++ /dev/null @@ -1,524 +0,0 @@ -var fs = require('fs'); -var esprima = require('./contrib/esprima'); -var escodegen = require('./contrib/escodegen'); -var EventEmitter = require('events').EventEmitter; - -esprima.Syntax = { - AssignmentExpression: 'AssignmentExpression', - ArrayExpression: 'ArrayExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - Program: 'Program', - Property: 'Property', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SwitchStatement: 'SwitchStatement', - SwitchCase: 'SwitchCase', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement' -}; - -module.exports = function(src) { - var instrumentor = new Instrumentor(src); - return instrumentor; -}; - -module.exports.Instrumentor = Instrumentor; - -function Instrumentor(src) { - // Setup our names - this.names = { - statement: this.generateName(6, "__statement_"), - expression: this.generateName(6, "__expression_"), - block: this.generateName(6, "__block_") - }; - - // Setup the node store - this.nodes = {}; - - // Setup the counters - this.blockCounter = 0; - this.nodeCounter = 0; - - if (src) { - this.instrumentedSource = this.instrument(src); - } -}; - -Instrumentor.prototype = new EventEmitter; - -Instrumentor.prototype.objectify = function() { - var obj = {}; - obj.blockCounter = this.blockCounter; - obj.nodeCounter = this.nodeCounter; - obj.source = this.source; - - obj.nodes = {}; - for(var key in this.nodes) { - if (this.nodes.hasOwnProperty(key)) { - var node = this.nodes[key]; - obj.nodes[key] = { loc: node.loc, id: node.id }; - } - } - - return obj; -} - -Instrumentor.prototype.filter = function(action) { - action = action || function() {}; - - var filtered = []; - for(var key in this.nodes) { - if (this.nodes.hasOwnProperty(key)) { - var node = this.nodes[key]; - if (action(node)) { - filtered.push(node); - } - } - } - - return filtered; -}; - -Instrumentor.prototype.instrument = function(code) { - this.source = code; - - // We wrap the code with a function to make sure it is compliant with node - var header = "(function() {"; - var footer = "\n})();" - var wrappedCode = header + code + footer; - - // Parse the wrapped code - var tree = esprima.parse(wrappedCode, {range: true, loc: true, comment: true}); - - var ignoredLines = {}; - var ignoreRe = /^\s*cover\s*:\s*false\s*$/ - tree.comments. - filter(function(commentNode) { - return ignoreRe.test(commentNode.value); - }). - forEach(function(commentNode) { - ignoredLines[commentNode.loc.start.line] = true; - }); - - // We only "instrument" the original part, which is in this sub-statement - this.wrap(tree.body[0].expression.callee.body.body, ignoredLines); - - // We need to adjust the nodes for everything on the first line, - // such that their location statements will start at 1 and not at header.length - for(var nodeKey in this.nodes) { - if (this.nodes.hasOwnProperty(nodeKey)) { - var node = this.nodes[nodeKey]; - - if (node.loc.start.line === 1 || node.loc.end.line === 1) { - // Copy over the location data, as these are shared across - // nodes. We only do it for things on the first line - node.loc = { - start: { - line: node.loc.start.line, - column: node.loc.start.column - }, - end: { - line: node.loc.end.line, - column: node.loc.end.column - } - } - - // Adjust the columns - if (node.loc.start.line == 1) { - node.loc.start.column = node.loc.start.column - header.length; - } - if (node.loc.end.line == 1) { - node.loc.end.column = node.loc.end.column - header.length; - } - } - } - } - - return escodegen.generate(tree); -}; - -Instrumentor.prototype.addToContext = function(context) { - context = context || {}; - - var that = this; - - context[that.names.expression] = function (i) { - var node = that.nodes[i]; - that.emit('node', node); - - return function (expr) { - return expr; - }; - }; - - context[that.names.statement] = function (i) { - var node = that.nodes[i]; - that.emit('node', node); - }; - - context[that.names.block] = function (i) { - that.emit('block', i); - }; - - return context; -}; - -Instrumentor.prototype.generateName = function (len, prefix) { - var name = ''; - var lower = '$'.charCodeAt(0); - var upper = 'z'.charCodeAt(0); - - while (name.length < len) { - var c = String.fromCharCode(Math.floor( - Math.random() * (upper - lower + 1) + lower - )); - if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; - } - - return prefix + name; -}; - -Instrumentor.prototype.traverseAndWrap = function(object, visitor, master) { - var key, child, parent, path; - - parent = (typeof master === 'undefined') ? [] : master; - - var returned = visitor.call(null, object, parent); - if (returned === false) { - return; - } - - for (key in object) { - if (object.hasOwnProperty(key)) { - child = object[key]; - path = [ object ]; - path.push(parent); - var newNode; - if (typeof child === 'object' && child !== null && !object.noCover) { - newNode = this.traverseAndWrap(child, visitor, path); - } - - if (newNode) { - object[key] = newNode; - newNode = null; - } - } - } - - return object.noCover ? undefined : returned; -}; - -Instrumentor.prototype.wrap = function(tree, ignoredLines) { - var that = this; - this.traverseAndWrap(tree, function(node, path) { - if (node.noCover) { - return; - } - if (node.loc && node.loc.start.line in ignoredLines) { - return false; - } - - parent = path[0]; - switch(node.type) { - case esprima.Syntax.ExpressionStatement: - case esprima.Syntax.ThrowStatement: - case esprima.Syntax.VariableDeclaration: { - if (parent && ( - (parent.type === esprima.Syntax.ForInStatement) || - (parent.type === esprima.Syntax.ForStatement) - )) { - return; - } - - var newNode = { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.statement - }, - "arguments": [ - { - "type": "Literal", - "value": that.nodeCounter++ - } - ] - } - }, - node - ] - } - that.nodes[that.nodeCounter - 1] = node; - node.id = that.nodeCounter - 1; - - return newNode; - } - case esprima.Syntax.ReturnStatement: { - var newNode = { - "type": "SequenceExpression", - "expressions": [ - { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.expression - }, - "arguments": [ - { - "type": "Identifier", - "name": that.nodeCounter++ - } - ], - noCover: true - } - ], - } - - if (node.argument) { - newNode.expressions.push(node.argument); - } - - that.nodes[that.nodeCounter - 1] = node; - node.id = that.nodeCounter - 1; - - node.argument = newNode - break; - } - case esprima.Syntax.ConditionalExpression: { - var newConsequentNode = { - "type": "SequenceExpression", - "expressions": [ - { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.expression - }, - "arguments": [ - { - "type": "Identifier", - "name": that.nodeCounter++ - } - ], - noCover: true - }, - node.consequent - ], - } - that.nodes[that.nodeCounter - 1] = node.consequent; - node.consequent.id = that.nodeCounter - 1 - - var newAlternateNode = { - "type": "SequenceExpression", - "expressions": [ - { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.expression - }, - "arguments": [ - { - "type": "Identifier", - "name": that.nodeCounter++ - } - ], - noCover: true - }, - node.alternate - ], - } - that.nodes[that.nodeCounter - 1] = node.alternate; - node.alternate.id = that.nodeCounter - 1 - - node.consequent = newConsequentNode; - node.alternate = newAlternateNode; - break; - } - case esprima.Syntax.BinaryExpression: - case esprima.Syntax.UpdateExpression: - case esprima.Syntax.LogicalExpression: - case esprima.Syntax.CallExpression: - case esprima.Syntax.UnaryExpression: - case esprima.Syntax.Identifier: { - // Only instrument Identifier in certain context. - if (node.type === esprima.Syntax.Identifier) { - if (!(parent && (parent.type == 'UnaryExpression' || - parent.type == 'BinaryExpression' || - parent.type == 'LogicalExpression' || - parent.type == 'ConditionalExpression' || - parent.type == 'SwitchStatement' || - parent.type == 'SwitchCase' || - parent.type == 'ForStatement' || - parent.type == 'IfStatement' || - parent.type == 'WhileStatement' || - parent.type == 'DoWhileStatement'))) { - return; - } - // Do not instrument Identifier when preceded by typeof - if (parent.operator == 'typeof') { - return; - } - - } - var newNode = { - "type": "SequenceExpression", - "expressions": [ - { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.expression - }, - "arguments": [ - { - "type": "Identifier", - "name": that.nodeCounter++ - } - ] - }, - node - ] - } - - that.nodes[that.nodeCounter - 1] = node; - node.id = that.nodeCounter - 1; - - return newNode - } - case esprima.Syntax.BlockStatement: { - var newNode = { - "type": "ExpressionStatement", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": that.names.block - }, - "arguments": [ - { - "type": "Literal", - "value": that.blockCounter++ - } - ] - }, - "noCover": true - } - - node.body.unshift(newNode) - break; - } - case esprima.Syntax.ForStatement: - case esprima.Syntax.ForInStatement: - case esprima.Syntax.LabeledStatement: - case esprima.Syntax.WhileStatement: - case esprima.Syntax.WithStatement: - case esprima.Syntax.CatchClause: - case esprima.Syntax.DoWhileStatement: { - if (node.body && node.body.type !== esprima.Syntax.BlockStatement) { - var newNode = { - "type": "BlockStatement", - "body": [ - node.body - ] - } - - node.body = newNode; - } - break; - } - case esprima.Syntax.TryStatement: { - if (node.block && node.block.type !== esprima.Syntax.BlockStatement) { - var newNode = { - "type": "BlockStatement", - "body": [ - node.block - ] - } - - node.block = newNode; - } - if (node.finalizer && node.finalizer.type !== esprima.Syntax.BlockStatement) { - var newNode = { - "type": "BlockStatement", - "body": [ - node.block - ] - } - - node.finalizer = newNode; - } - break; - } - case esprima.Syntax.SwitchCase: { - if (node.consequent && node.consequent.length > 0 && - (node.consequent.length != 1 || node.consequent[0].type !== esprima.Syntax.BlockStatement)) { - var newNode = { - "type": "BlockStatement", - "body": node.consequent - } - - node.consequent = [newNode]; - } - break; - } - case esprima.Syntax.IfStatement: { - if (node.consequent && node.consequent.type !== esprima.Syntax.BlockStatement) { - var newNode = { - "type": "BlockStatement", - "body": [ - node.consequent - ] - } - - node.consequent = newNode; - } - if (node.alternate && node.alternate.type !== esprima.Syntax.BlockStatement - && node.alternate.type !== esprima.Syntax.IfStatement) { - var newNode = { - "type": "BlockStatement", - "body": [ - node.alternate - ] - } - - node.alternate = newNode; - } - break; - } - } - }); -} diff --git a/templates/file.html b/mocha/cover_html/_Users_itay_Work_mocha_index.js.html similarity index 63% rename from templates/file.html rename to mocha/cover_html/_Users_itay_Work_mocha_index.js.html index dfd1220..3a47a44 100644 --- a/templates/file.html +++ b/mocha/cover_html/_Users_itay_Work_mocha_index.js.html @@ -3,7 +3,7 @@ - <%= filename %> -- cover.io + /Users/itay/Work/mocha/index.js -- cover.io @@ -36,34 +36,49 @@ table#files-table td:first-child, table#files-table th:first-child { width: 33%; } - - .partialuncovered { - background: #EE9; - } - - pre.prettyprint { - padding-top: 0em; - border: 5px; - padding-left: 0em; - padding-bottom: 0em; - font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; - - } + + li.L0,li.L1,li.L2,li.L3,li.L4, li.L5,li.L6,li.L7,li.L8, li.L9 { background: transparent; } + li.L1,li.L3,li.L5,li.L7,li.L9 { background: white; } - span.covered { + li.covered { border-left: 2px solid lime; } - span.uncovered { + li.uncovered { background: #FDD; border-left: 2px solid red; } - span.partial { + li.partial { border-left: 2px solid #EE9; background: #FFA; } + .partialuncovered { + background: #EE9; + } + + ol.linenums { + font-size: 10px; + } + + ol.linenums li { + line-height: 16px; + } + + ol.linenums li span { + font-size: 12px; + } + + pre.prettyprint { + padding-top: 1em; + border: 5px; + padding-left: 1.5em; + padding-bottom: 2em; + font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; + + } + div.header { width: 100%; padding: 0; @@ -119,41 +134,17 @@ color: gray; } - table.code td.text { - padding-left: 0px; - padding-right: 0px; - } - - .linenos p { - text-align: left; - margin: 0; - padding-right: 0.5em; - color: #999999; - font-family: verdana, sans-serif; - font-size: 0.8em; /* 12/16 */ - line-height: 16px; /* 16/12 */ - } - - td.text { - width: 100%; - height: 16px; - } - - td.text pre > span { - padding-top: 3px; - line-height: 16px; - } - + @@ -170,25 +161,22 @@
« index -

Coverage for <%= filename %> : <%= stats.percentage %>

+

Coverage for /Users/itay/Work/mocha/index.js : 100%

- <%= stats.totalLines %> lines | - <%= stats.seenLines %> run | - <%= stats.missingLines %> missing | - <%= stats.partialLines %> partial | - <%= stats.totalBlocks %> blocks | - <%= stats.seenBlocks %> blocks run | - <%= stats.missingBlocks %> blocks missing + 2 lines | + 2 run | + 0 missing | + 0 partial | + 2 blocks | + 2 blocks run | + 0 blocks missing
- - - - <%= code %> - - -
+
+  
+  module.exports = require('./lib/mocha');
+
« index | cover.io diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_browser_progress.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_browser_progress.js.html new file mode 100644 index 0000000..384c685 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_browser_progress.js.html @@ -0,0 +1,307 @@ + + + + + + /Users/itay/Work/mocha/lib/browser/progress.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/browser/progress.js : 78%

+
+ 126 lines | + 99 run | + 27 missing | + 0 partial | + 26 blocks | + 1 blocks run | + 25 blocks missing +
+
+
+
+  
+  /**
+   * Expose `Progress`.
+   */
+  
+  module.exports = Progress;
+  
+  /**
+   * Initialize a new `Progress` indicator.
+   */
+  
+  function Progress() {
+    this.percent = 0;
+    this.size(0);
+    this.fontSize(12);
+    this.font('helvetica, arial, sans-serif');
+  }
+  
+  /**
+   * Set progress size to `n`.
+   *
+   * @param {Number} n
+   * @return {Progress} for chaining
+   * @api public
+   */
+  
+  Progress.prototype.size = function(n){
+    this._size = n;
+    return this;
+  };
+  
+  /**
+   * Set text to `str`.
+   *
+   * @param {String} str
+   * @return {Progress} for chaining
+   * @api public
+   */
+  
+  Progress.prototype.text = function(str){
+    this._text = str;
+    return this;
+  };
+  
+  /**
+   * Set font size to `n`.
+   *
+   * @param {Number} n
+   * @return {Progress} for chaining
+   * @api public
+   */
+  
+  Progress.prototype.fontSize = function(n){
+    this._fontSize = n;
+    return this;
+  };
+  
+  /**
+   * Set font `family`.
+   *
+   * @param {String} family
+   * @return {Progress} for chaining
+   */
+  
+  Progress.prototype.font = function(family){
+    this._font = family;
+    return this;
+  };
+  
+  /**
+   * Update percentage to `n`.
+   *
+   * @param {Number} n
+   * @return {Progress} for chaining
+   */
+  
+  Progress.prototype.update = function(n){
+    this.percent = n;
+    return this;
+  };
+  
+  /**
+   * Draw on `ctx`.
+   *
+   * @param {CanvasRenderingContext2d} ctx
+   * @return {Progress} for chaining
+   */
+  
+  Progress.prototype.draw = function(ctx){
+    var percent = Math.min(this.percent, 100)
+      , size = this._size
+      , half = size / 2
+      , x = half
+      , y = half
+      , rad = half - 1
+      , fontSize = this._fontSize;
+  
+    ctx.font = fontSize + 'px ' + this._font;
+  
+    var angle = Math.PI * 2 * (percent / 100);
+    ctx.clearRect(0, 0, size, size);
+  
+    // outer circle
+    ctx.strokeStyle = '#9f9f9f';
+    ctx.beginPath();
+    ctx.arc(x, y, rad, 0, angle, false);
+    ctx.stroke();
+  
+    // inner circle
+    ctx.strokeStyle = '#eee';
+    ctx.beginPath();
+    ctx.arc(x, y, rad - 1, 0, angle, true);
+    ctx.stroke();
+  
+    // text
+    var text = this._text || (percent | 0) + '%'
+      , w = ctx.measureText(text).width;
+  
+    ctx.fillText(
+        text
+      , x - w / 2 + 1
+      , y + fontSize / 2 - 1);
+  
+    return this;
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_hook.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_hook.js.html new file mode 100644 index 0000000..15b7c4e --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_hook.js.html @@ -0,0 +1,212 @@ + + + + + + /Users/itay/Work/mocha/lib/hook.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/hook.js : 96%

+
+ 31 lines | + 30 run | + 1 missing | + 0 partial | + 4 blocks | + 2 blocks run | + 2 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Runnable = require('./runnable');
+  
+  /**
+   * Expose `Hook`.
+   */
+  
+  module.exports = Hook;
+  
+  /**
+   * Initialize a new `Hook` with the given `title` and callback `fn`.
+   *
+   * @param {String} title
+   * @param {Function} fn
+   * @api private
+   */
+  
+  function Hook(title, fn) {
+    Runnable.call(this, title, fn);
+  }
+  
+  /**
+   * Inherit from `Runnable.prototype`.
+   */
+  
+  Hook.prototype.__proto__ = Runnable.prototype;
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_bdd.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_bdd.js.html new file mode 100644 index 0000000..1acdd7c --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_bdd.js.html @@ -0,0 +1,268 @@ + + + + + + /Users/itay/Work/mocha/lib/interfaces/bdd.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/interfaces/bdd.js : 82%

+
+ 87 lines | + 72 run | + 15 missing | + 0 partial | + 20 blocks | + 4 blocks run | + 16 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Suite = require('../suite')
+    , Test = require('../test');
+  
+  /**
+   * BDD-style interface:
+   * 
+   *      describe('Array', function(){
+   *        describe('#indexOf()', function(){
+   *          it('should return -1 when not present', function(){
+   *
+   *          });
+   *
+   *          it('should return the index when present', function(){
+   *
+   *          });
+   *        });
+   *      });
+   * 
+   */
+  
+  module.exports = function(suite){
+    var suites = [suite];
+  
+    suite.on('pre-require', function(context){
+  
+      /**
+       * Execute before running tests.
+       */
+  
+      context.before = function(fn){
+        suites[0].beforeAll(fn);
+      };
+  
+      /**
+       * Execute after running tests.
+       */
+  
+      context.after = function(fn){
+        suites[0].afterAll(fn);
+      };
+  
+      /**
+       * Execute before each test case.
+       */
+  
+      context.beforeEach = function(fn){
+        suites[0].beforeEach(fn);
+      };
+  
+      /**
+       * Execute after each test case.
+       */
+  
+      context.afterEach = function(fn){
+        suites[0].afterEach(fn);
+      };
+  
+      /**
+       * Describe a "suite" with the given `title`
+       * and callback `fn` containing nested suites
+       * and/or tests.
+       */
+    
+      context.describe = function(title, fn){
+        var suite = Suite.create(suites[0], title);
+        suites.unshift(suite);
+        fn();
+        suites.shift();
+      };
+  
+      /**
+       * Describe a specification or test-case
+       * with the given `title` and callback `fn`
+       * acting as a thunk.
+       */
+  
+      context.it = function(title, fn){
+        suites[0].addTest(new Test(title, fn));
+      };
+    });
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_exports.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_exports.js.html new file mode 100644 index 0000000..8f1f49b --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_exports.js.html @@ -0,0 +1,241 @@ + + + + + + /Users/itay/Work/mocha/lib/interfaces/exports.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/interfaces/exports.js : 76%

+
+ 60 lines | + 46 run | + 14 missing | + 0 partial | + 18 blocks | + 2 blocks run | + 16 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Suite = require('../suite')
+    , Test = require('../test');
+  
+  /**
+   * TDD-style interface:
+   * 
+   *     exports.Array = {
+   *       '#indexOf()': {
+   *         'should return -1 when the value is not present': function(){
+   *           
+   *         },
+   *
+   *         'should return the correct index when the value is present': function(){
+   *           
+   *         }
+   *       }
+   *     };
+   * 
+   */
+  
+  module.exports = function(suite){
+    var suites = [suite];
+  
+    suite.on('require', visit);
+  
+    function visit(obj) {
+      var suite;
+      for (var key in obj) {
+        if ('function' == typeof obj[key]) {
+          var fn = obj[key];
+          switch (key) {
+            case 'before':
+              suites[0].beforeAll(fn);
+              break;
+            case 'after':
+              suites[0].afterAll(fn);
+              break;
+            case 'beforeEach':
+              suites[0].beforeEach(fn);
+              break;
+            case 'afterEach':
+              suites[0].afterEach(fn);
+              break;
+            default:
+              suites[0].addTest(new Test(key, fn));
+          }
+        } else {
+          var suite = Suite.create(suites[0], key);
+          suites.unshift(suite);
+          visit(obj[key]);
+          suites.shift();
+        }
+      }
+    }
+  };
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_index.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_index.js.html new file mode 100644 index 0000000..18d5e7a --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_index.js.html @@ -0,0 +1,185 @@ + + + + + + /Users/itay/Work/mocha/lib/interfaces/index.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/interfaces/index.js : 100%

+
+ 4 lines | + 4 run | + 0 missing | + 0 partial | + 4 blocks | + 4 blocks run | + 0 blocks missing +
+
+
+
+  
+  exports.bdd = require('./bdd');
+  exports.tdd = require('./tdd');
+  exports.exports = require('./exports');
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_tdd.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_tdd.js.html new file mode 100644 index 0000000..e1c5347 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_interfaces_tdd.js.html @@ -0,0 +1,276 @@ + + + + + + /Users/itay/Work/mocha/lib/interfaces/tdd.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/interfaces/tdd.js : 82%

+
+ 95 lines | + 78 run | + 17 missing | + 0 partial | + 20 blocks | + 2 blocks run | + 18 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Suite = require('../suite')
+    , Test = require('../test');
+  
+  /**
+   * TDD-style interface:
+   *
+   *      suite('Array', function(){
+   *        suite('#indexOf()', function(){
+   *          suiteSetup(function(){
+   *
+   *          });
+   *          
+   *          test('should return -1 when not present', function(){
+   *
+   *          });
+   *
+   *          test('should return the index when present', function(){
+   *
+   *          });
+   *
+   *          suiteTeardown(function(){
+   *
+   *          });
+   *        });
+   *      });
+   *
+   */
+  
+  module.exports = function(suite){
+    var suites = [suite];
+  
+    suite.on('pre-require', function(context){
+  
+      /**
+       * Execute before each test case.
+       */
+  
+      context.setup = function(fn){
+        suites[0].beforeEach(fn);
+      };
+  
+      /**
+       * Execute after each test case.
+       */
+  
+      context.teardown = function(fn){
+        suites[0].afterEach(fn);
+      };
+  
+      /**
+       * Execute before the suite.
+       */
+  
+      context.suiteSetup = function(fn){
+        suites[0].beforeAll(fn);
+      };
+  
+      /**
+       * Execute after the suite.
+       */
+  
+      context.suiteTeardown = function(fn){
+        suites[0].afterAll(fn);
+      };
+  
+      /**
+       * Describe a "suite" with the given `title`
+       * and callback `fn` containing nested suites
+       * and/or tests.
+       */
+  
+      context.suite = function(title, fn){
+        var suite = Suite.create(suites[0], title);
+        suites.unshift(suite);
+        fn();
+        suites.shift();
+      };
+  
+      /**
+       * Describe a specification or test-case
+       * with the given `title` and callback `fn`
+       * acting as a thunk.
+       */
+  
+      context.test = function(title, fn){
+        suites[0].addTest(new Test(title, fn));
+      };
+    });
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_mocha.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_mocha.js.html new file mode 100644 index 0000000..c663f20 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_mocha.js.html @@ -0,0 +1,204 @@ + + + + + + /Users/itay/Work/mocha/lib/mocha.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/mocha.js : 100%

+
+ 23 lines | + 23 run | + 0 missing | + 0 partial | + 10 blocks | + 10 blocks run | + 0 blocks missing +
+
+
+
+  
+  /*!
+   * mocha
+   * Copyright(c) 2011 TJ Holowaychuk 
+   * MIT Licensed
+   */
+  
+  /**
+   * Library version.
+   */
+  
+  exports.version = '0.7.0';
+  
+  exports.utils = require('./utils');
+  exports.interfaces = require('./interfaces');
+  exports.reporters = require('./reporters');
+  exports.Runnable = require('./runnable');
+  exports.Runner = require('./runner');
+  exports.Suite = require('./suite');
+  exports.Hook = require('./hook');
+  exports.Test = require('./test');
+  exports.watch = require('./watch');
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_base.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_base.js.html new file mode 100644 index 0000000..30c4da1 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_base.js.html @@ -0,0 +1,405 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/base.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/base.js : 76%

+
+ 224 lines | + 172 run | + 52 missing | + 0 partial | + 53 blocks | + 4 blocks run | + 49 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var tty = require('tty');
+  
+  /**
+   * Check if both stdio streams are associated with a tty.
+   */
+  
+  var isatty = tty.isatty(1) && tty.isatty(2);
+  
+  /**
+   * Expose `Base`.
+   */
+  
+  exports = module.exports = Base;
+  
+  /**
+   * Enable coloring by default.
+   */
+  
+  exports.useColors = isatty;
+  
+  /**
+   * Default color map.
+   */
+  
+  exports.colors = {
+      'pass': 90
+    , 'fail': 31
+    , 'bright pass': 92
+    , 'bright fail': 91
+    , 'bright yellow': 93
+    , 'pending': 36
+    , 'suite': 0
+    , 'error title': 0
+    , 'error message': 31
+    , 'error stack': 90
+    , 'checkmark': 32
+    , 'fast': 90
+    , 'medium': 33
+    , 'slow': 31
+    , 'green': 32
+    , 'light': 90
+  };
+  
+  /**
+   * Color `str` with the given `type`,
+   * allowing colors to be disabled,
+   * as well as user-defined color
+   * schemes.
+   *
+   * @param {String} type
+   * @param {String} str
+   * @return {String}
+   * @api private
+   */
+  
+  var color = exports.color = function(type, str) {
+    if (!exports.useColors) return str;
+    return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
+  };
+  
+  /**
+   * Expose term window size, with some
+   * defaults for when stderr is not a tty.
+   */
+  
+  exports.window = {
+    width: isatty
+      ? process.stdout.getWindowSize
+        ? process.stdout.getWindowSize(1)[0]
+        : tty.getWindowSize()[1]
+      : 75
+  };
+  
+  /**
+   * Expose some basic cursor interactions
+   * that are common among reporters.
+   */
+  
+  exports.cursor = {
+    hide: function(){
+      process.stdout.write('\033[?25l');
+    },
+  
+    show: function(){
+      process.stdout.write('\033[?25h');
+    }
+  };
+  
+  /**
+   * A test is considered slow if it
+   * exceeds the following value in milliseconds.
+   */
+  
+  exports.slow = 75;
+  
+  /**
+   * Outut the given `failures` as a list.
+   *
+   * @param {Array} failures
+   * @api public
+   */
+  
+  exports.list = function(failures){
+    console.error();
+    failures.forEach(function(test, i){
+      // format
+      var fmt = color('error title', '  %s) %s:\n')
+        + color('error message', '     %s')
+        + color('error stack', '\n%s\n');
+  
+      // msg
+      var err = test.err
+        , stack = err.stack
+        , message = err.message || ''
+        , index = stack.indexOf(message) + message.length
+        , msg = stack.slice(0, index);
+  
+      // indent stack trace without msg
+      stack = stack.slice(index + 1)
+        .replace(/^/gm, '  ');
+  
+      console.error(fmt, i, test.fullTitle(), msg, stack);
+    });
+  };
+  
+  /**
+   * Initialize a new `Base` reporter.
+   *
+   * All other reporters generally
+   * inherit from this reporter, providing
+   * stats such as test duration, number
+   * of tests passed / failed etc.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function Base(runner) {
+    var self = this
+      , stats = this.stats = { suites: 0, tests: 0, passes: 0, failures: 0 }
+      , failures = this.failures = [];
+  
+    if (!runner) return;
+    this.runner = runner;
+  
+    runner.on('start', function(){
+      stats.start = new Date;
+    });
+  
+    runner.on('suite', function(suite){
+      stats.suites = stats.suites || 0;
+      stats.suites++;
+    });
+  
+    runner.on('test end', function(test){
+      stats.tests = stats.tests || 0;
+      stats.tests++;
+    });
+  
+    runner.on('pass', function(test){
+      stats.passes = stats.passes || 0;
+  
+      var medium = exports.slow / 2;
+      test.speed = test.duration > exports.slow
+        ? 'slow'
+        : test.duration > medium
+          ? 'medium'
+          : 'fast';
+  
+      stats.passes++;
+    });
+  
+    runner.on('fail', function(test, err){
+      stats.failures = stats.failures || 0;
+      stats.failures++;
+      test.err = err;
+      failures.push(test);
+    });
+  
+    runner.on('end', function(){
+      stats.end = new Date;
+      stats.duration = new Date - stats.start;
+    });
+  }
+  
+  /**
+   * Output common epilogue used by many of
+   * the bundled reporters.
+   *
+   * @api public
+   */
+  
+  Base.prototype.epilogue = function(){
+    var stats = this.stats
+      , fmt;
+  
+    console.log();
+  
+    // failure
+    if (stats.failures) {
+      fmt = color('bright fail', '  ✖')
+        + color('fail', ' %d of %d tests failed')
+        + color('light', ':')
+  
+      console.error(fmt, stats.failures, this.runner.total);
+      Base.list(this.failures);
+      console.error();
+      return;
+    }
+  
+    // pass
+    fmt = color('bright pass', '  ✔')
+      + color('green', ' %d tests complete')
+      + color('light', ' (%dms)');
+  
+    console.log(fmt, stats.tests || 0, stats.duration);
+    console.log();
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_doc.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_doc.js.html new file mode 100644 index 0000000..1518745 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_doc.js.html @@ -0,0 +1,255 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/doc.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/doc.js : 70%

+
+ 74 lines | + 52 run | + 22 missing | + 0 partial | + 36 blocks | + 2 blocks run | + 34 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , utils = require('../utils');
+  
+  /**
+   * Expose `Doc`.
+   */
+  
+  exports = module.exports = Doc;
+  
+  /**
+   * Initialize a new `Doc` reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function Doc(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , total = runner.total
+      , indents = 2;
+  
+    function indent() {
+      return Array(indents).join('  ');
+    }
+  
+    runner.on('suite', function(suite){
+      if (suite.root) return;
+      ++indents;
+      console.log('%s<section class="suite">', indent());
+      ++indents;
+      console.log('%s<h1>%s</h1>', indent(), suite.title);
+      console.log('%s<dl>', indent());
+    });
+  
+    runner.on('suite end', function(suite){
+      if (suite.root) return;
+      console.log('%s</dl>', indent());
+      --indents;
+      console.log('%s</section>', indent());
+      --indents;
+    });
+  
+    runner.on('pass', function(test){
+      console.log('%s  <dt>%s</dt>', indent(), test.title);
+      var code = utils.escape(clean(test.fn.toString()));
+      console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);
+    });
+  }
+  
+  /**
+   * Strip the function definition from `str`,
+   * and re-indent for pre whitespace.
+   */
+  
+  function clean(str) {
+    str = str
+      .replace(/^function *\(.*\) *{/, '')
+      .replace(/\s+\}$/, '');
+  
+    var spaces = str.match(/^\n?( *)/)[1].length
+      , re = new RegExp('^ {' + spaces + '}', 'gm');
+  
+    str = str.replace(re, '');
+  
+    return str;
+  }
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_dot.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_dot.js.html new file mode 100644 index 0000000..f336e9f --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_dot.js.html @@ -0,0 +1,243 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/dot.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/dot.js : 70%

+
+ 62 lines | + 44 run | + 18 missing | + 0 partial | + 32 blocks | + 2 blocks run | + 30 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , color = Base.color;
+  
+  /**
+   * Expose `Dot`.
+   */
+  
+  exports = module.exports = Dot;
+  
+  /**
+   * Initialize a new `Dot` matrix test reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function Dot(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , width = Base.window.width * .75 | 0
+      , n = 0;
+  
+    runner.on('start', function(){
+      process.stdout.write('\n  ');
+    });
+  
+    runner.on('pending', function(test){
+      process.stdout.write(color('pending', '.'));
+    });
+  
+    runner.on('pass', function(test){
+      if (++n % width == 0) process.stdout.write('\n  ');
+      if ('slow' == test.speed) {
+        process.stdout.write(color('bright yellow', '.'));
+      } else {
+        process.stdout.write(color(test.speed, '.'));
+      }
+    });
+  
+    runner.on('fail', function(test, err){
+      if (++n % width == 0) process.stdout.write('\n  ');
+      process.stdout.write(color('fail', '.'));
+    });
+  
+    runner.on('end', function(){
+      console.log();
+      self.epilogue();
+    });
+  }
+  
+  /**
+   * Inherit from `Base.prototype`.
+   */
+  
+  Dot.prototype.__proto__ = Base.prototype;
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_html.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_html.js.html new file mode 100644 index 0000000..39c48fc --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_html.js.html @@ -0,0 +1,334 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/html.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/html.js : 71%

+
+ 153 lines | + 109 run | + 44 missing | + 0 partial | + 75 blocks | + 3 blocks run | + 72 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , utils = require('../utils')
+    , Progress = require('../browser/progress')
+    , escape = utils.escape;
+  
+  /**
+   * Expose `Doc`.
+   */
+  
+  exports = module.exports = HTML;
+  
+  /**
+   * Stats template.
+   */
+  
+  var statsTemplate = '
    ' + + '
  • '
    + + '
  • passes: 0
  • '
    + + '
  • failures: 0
  • '
    + + '
  • duration: 0s
  • '
    + + '
';
+ + /** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + + function HTML(runner) { + Base.call(this, runner); + + // TODO: clean up + + var self = this + , stats = this.stats + , total = runner.total + , root = $('#mocha') + , stack = [root] + , stat = $(statsTemplate).appendTo(root) + , canvas = stat.find('canvas').get(0) + , ctx, progress + + if (canvas.getContext) { + ctx = canvas.getContext('2d'); + progress = new Progress; + } + + if (!root.length) return error('#mocha div missing, add it to your document'); + + if (progress) { + progress.size(50); + } + + runner.on('suite', function(suite){ + if (suite.root) return; + + // suite + var el = $('<div class="suite"><h1>' + suite.title + '</h1></div>'); + + // container + stack[0].append(el); + stack.unshift($('<div>')); + el.append(stack[0]); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + stack.shift(); + }); + + runner.on('fail', function(test, err){ + if (err.uncaught) runner.emit('test end', test); + }); + + runner.on('test end', function(test){ + // TODO: add to stats + var percent = stats.tests / total * 100 | 0; + + if (progress) { + // update progress bar + progress.update(percent).draw(ctx); + } + + // update stats + var ms = new Date - stats.start; + stat.find('.passes em').text(stats.passes); + stat.find('.failures em').text(stats.failures); + stat.find('.duration em').text((ms / 1000).toFixed(2)); + + // test + if (test.passed) { + var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>') + } else if (test.pending) { + var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>') + } else { + var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>'); + var str = test.err.stack || test.err; + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if ('[object Error]' == str) str = test.err.message; + + $('<pre class="error">' + escape(str) + '</pre>').appendTo(el); + } + + // toggle code + el.find('h2').toggle(function(){ + pre.slideDown('fast'); + }, function(){ + pre.slideUp('fast'); + }); + + // code + // TODO: defer + if (!test.pending) { + var code = escape(clean(test.fn.toString())); + var pre = $('<pre><code>' + code + '</code></pre>'); + pre.appendTo(el).hide(); + } + stack[0].append(el); + }); + } + + function error(msg) { + $('<div id="error">' + msg + '</div>').appendTo('body'); + } + + /** + * Strip the function definition from `str`, + * and re-indent for pre whitespace. + */ + + function clean(str) { + str = str + .replace(/^function *\(.*\) *{/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length + , re = new RegExp('^ {' + spaces + '}', 'gm'); + + str = str + .replace(re, '') + .replace(/^\s+/, ''); + + return str; + } + +
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_index.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_index.js.html new file mode 100644 index 0000000..4fc2430 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_index.js.html @@ -0,0 +1,194 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/index.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/index.js : 100%

+
+ 13 lines | + 13 run | + 0 missing | + 0 partial | + 12 blocks | + 12 blocks run | + 0 blocks missing +
+
+
+
+  
+  exports.Base = require('./base');
+  exports.Dot = require('./dot');
+  exports.Doc = require('./doc');
+  exports.TAP = require('./tap');
+  exports.JSON = require('./json');
+  exports.HTML = require('./html');
+  exports.List = require('./list');
+  exports.Spec = require('./spec');
+  exports.Progress = require('./progress');
+  exports.Landing = require('./landing');
+  exports.JSONStream = require('./json-stream');
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json-stream.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json-stream.js.html new file mode 100644 index 0000000..64b6042 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json-stream.js.html @@ -0,0 +1,242 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/json-stream.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/json-stream.js : 81%

+
+ 61 lines | + 50 run | + 11 missing | + 0 partial | + 23 blocks | + 2 blocks run | + 21 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , color = Base.color;
+  
+  /**
+   * Expose `List`.
+   */
+  
+  exports = module.exports = List;
+  
+  /**
+   * Initialize a new `List` test reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function List(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , total = runner.total;
+  
+    runner.on('start', function(){
+      console.log(JSON.stringify(['start', { total: total }]));
+    });
+  
+    runner.on('pass', function(test){
+      console.log(JSON.stringify(['pass', clean(test)]));
+    });
+  
+    runner.on('fail', function(test, err){
+      console.log(JSON.stringify(['fail', clean(test)]));
+    });
+  
+    runner.on('end', function(){
+      process.stdout.write(JSON.stringify(['end', self.stats]));
+    });
+  }
+  
+  /**
+   * Return a plain-object representation of `test`
+   * free of cyclic properties etc.
+   *
+   * @param {Object} test
+   * @return {Object}
+   * @api private
+   */
+  
+  function clean(test) {
+    return {
+        title: test.title
+      , fullTitle: test.fullTitle()
+      , duration: test.duration
+    }
+  }
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json.js.html new file mode 100644 index 0000000..64d21da --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_json.js.html @@ -0,0 +1,251 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/json.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/json.js : 77%

+
+ 70 lines | + 54 run | + 16 missing | + 0 partial | + 19 blocks | + 2 blocks run | + 17 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , cursor = Base.cursor
+    , color = Base.color;
+  
+  /**
+   * Expose `JSON`.
+   */
+  
+  exports = module.exports = JSONReporter;
+  
+  /**
+   * Initialize a new `JSON` reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function JSONReporter(runner) {
+    var self = this;
+    Base.call(this, runner);
+  
+    var tests = []
+      , failures = []
+      , passes = [];
+  
+    runner.on('test end', function(test){
+      tests.push(test);
+    });
+  
+    runner.on('pass', function(test){
+      passes.push(test);
+    });
+  
+    runner.on('fail', function(test){
+      failures.push(test);
+    });
+  
+    runner.on('end', function(){
+      var obj = {
+          stats: self.stats
+        , tests: tests.map(clean)
+        , failures: failures.map(clean)
+        , passes: passes.map(clean)
+      };
+  
+      process.stdout.write(JSON.stringify(obj));
+    });
+  }
+  
+  /**
+   * Return a plain-object representation of `test`
+   * free of cyclic properties etc.
+   *
+   * @param {Object} test
+   * @return {Object}
+   * @api private
+   */
+  
+  function clean(test) {
+    return {
+        title: test.title
+      , fullTitle: test.fullTitle()
+      , duration: test.duration
+    }
+  }
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_landing.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_landing.js.html new file mode 100644 index 0000000..c64eda9 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_landing.js.html @@ -0,0 +1,278 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/landing.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/landing.js : 72%

+
+ 97 lines | + 70 run | + 27 missing | + 0 partial | + 39 blocks | + 2 blocks run | + 37 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , cursor = Base.cursor
+    , color = Base.color;
+  
+  /**
+   * Expose `Landing`.
+   */
+  
+  exports = module.exports = Landing;
+  
+  /**
+   * Airplane color.
+   */
+  
+  Base.colors.plane = 0;
+  
+  /**
+   * Airplane crash color.
+   */
+  
+  Base.colors['plane crash'] = 31;
+  
+  /**
+   * Runway color.
+   */
+  
+  Base.colors.runway = 90;
+  
+  /**
+   * Initialize a new `Landing` reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function Landing(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , width = Base.window.width * .75 | 0
+      , total = runner.total
+      , stream = process.stdout
+      , plane = color('plane', '✈')
+      , crashed = -1
+      , n = 0;
+  
+    function runway() {
+      var buf = Array(width).join('-');
+      return '  ' + color('runway', buf);
+    }
+  
+    runner.on('start', function(){
+      stream.write('\n  ');
+      cursor.hide();
+    });
+  
+    runner.on('test end', function(test){
+      // check if the plane crashed
+      var col = -1 == crashed
+        ? width * ++n / total | 0
+        : crashed;
+  
+      // show the crash
+      if (test.failed) {
+        plane = color('plane crash', '✈');
+        crashed = col;
+      }
+  
+      // render landing strip
+      stream.write('\033[4F\n\n');
+      stream.write(runway());
+      stream.write('\n  ');
+      stream.write(color('runway', Array(col).join('⋅')));
+      stream.write(plane)
+      stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
+      stream.write(runway());
+      stream.write('\033[0m');
+    });
+  
+    runner.on('end', function(){
+      cursor.show();
+      console.log();
+      self.epilogue();
+    });
+  }
+  
+  /**
+   * Inherit from `Base.prototype`.
+   */
+  
+  Landing.prototype.__proto__ = Base.prototype;
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_list.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_list.js.html new file mode 100644 index 0000000..7d82bbc --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_list.js.html @@ -0,0 +1,242 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/list.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/list.js : 70%

+
+ 61 lines | + 43 run | + 18 missing | + 0 partial | + 32 blocks | + 2 blocks run | + 30 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , color = Base.color;
+  
+  /**
+   * Expose `List`.
+   */
+  
+  exports = module.exports = List;
+  
+  /**
+   * Initialize a new `List` test reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function List(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , n = 0;
+  
+    runner.on('start', function(){
+      console.log();
+    });
+  
+    runner.on('test', function(test){
+      process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));
+    });
+  
+    runner.on('pending', function(test){
+      var fmt = color('checkmark', '  -')
+        + color('pending', ' %s');
+      console.log(fmt, test.fullTitle());
+    });
+  
+    runner.on('pass', function(test){
+      var fmt = color('checkmark', '  ✓')
+        + color('pass', ' %s: ')
+        + color(test.speed, '%dms');
+      console.log('\r' + fmt, test.fullTitle(), test.duration);
+    });
+  
+    runner.on('fail', function(test, err){
+      console.log('\r' + color('fail', '  %d) %s'), n++, test.fullTitle());
+    });
+  
+    runner.on('end', self.epilogue.bind(self));
+  }
+  
+  /**
+   * Inherit from `Base.prototype`.
+   */
+  
+  List.prototype.__proto__ = Base.prototype;
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_progress.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_progress.js.html new file mode 100644 index 0000000..3011a7a --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_progress.js.html @@ -0,0 +1,265 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/progress.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/progress.js : 67%

+
+ 84 lines | + 57 run | + 27 missing | + 0 partial | + 31 blocks | + 2 blocks run | + 29 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , cursor = Base.cursor
+    , color = Base.color;
+  
+  /**
+   * Expose `Progress`.
+   */
+  
+  exports = module.exports = Progress;
+  
+  /**
+   * General progress bar color.
+   */
+  
+  Base.colors.progress = 90;
+  
+  /**
+   * Initialize a new `Progress` bar test reporter.
+   *
+   * @param {Runner} runner
+   * @param {Object} options
+   * @api public
+   */
+  
+  function Progress(runner, options) {
+    Base.call(this, runner);
+  
+    var self = this
+      , options = options || {}
+      , stats = this.stats
+      , width = Base.window.width * .50 | 0
+      , total = runner.total
+      , complete = 0
+      , max = Math.max;
+  
+    // default chars
+    options.open = options.open || '[';
+    options.complete = options.complete || '▬';
+    options.incomplete = options.incomplete || '⋅';
+    options.close = options.close || ']';
+    options.verbose = false;
+  
+    // tests started
+    runner.on('start', function(){
+      console.log();
+      cursor.hide();
+    });
+  
+    // tests complete
+    runner.on('test end', function(){
+      var incomplete = total - complete
+        , percent = complete++ / total
+        , n = width * percent | 0
+        , i = width - n;
+  
+      process.stdout.write('\r\033[J');
+      process.stdout.write(color('progress', '  ' + options.open));
+      process.stdout.write(Array(n).join(options.complete));
+      process.stdout.write(Array(i).join(options.incomplete));
+      process.stdout.write(color('progress', options.close));
+      if (options.verbose) {
+        process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
+      }
+    });
+  
+    // tests are complete, output some stats
+    // and the failures if any
+    runner.on('end', function(){
+      cursor.show();
+      console.log();
+      self.epilogue();
+    });
+  }
+  
+  /**
+   * Inherit from `Base.prototype`.
+   */
+  
+  Progress.prototype.__proto__ = Base.prototype;
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_spec.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_spec.js.html new file mode 100644 index 0000000..a71906d --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_spec.js.html @@ -0,0 +1,264 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/spec.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/spec.js : 63%

+
+ 83 lines | + 53 run | + 30 missing | + 0 partial | + 48 blocks | + 2 blocks run | + 46 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , color = Base.color;
+  
+  /**
+   * Expose `Spec`.
+   */
+  
+  exports = module.exports = Spec;
+  
+  /**
+   * Initialize a new `Spec` test reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function Spec(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , indents = 0
+      , n = 0;
+  
+    function indent() {
+      return Array(indents).join('  ')
+    }
+  
+    runner.on('start', function(){
+      console.log();
+    });
+  
+    runner.on('suite', function(suite){
+      ++indents;
+      console.log(color('suite', '%s%s'), indent(), suite.title);
+    });
+  
+    runner.on('suite end', function(suite){
+      --indents;
+      if (1 == indents) console.log();
+    });
+  
+    runner.on('test', function(test){
+      process.stdout.write(indent() + color('pass', '  ◦ ' + test.title + ': '));
+    });
+  
+    runner.on('pending', function(test){
+      var fmt = indent() + color('pending', '  - %s');
+      console.log(fmt, test.title);
+    });
+  
+    runner.on('pass', function(test){
+      if ('fast' == test.speed) {
+        var fmt = indent()
+          + color('checkmark', '  ✓')
+          + color('pass', ' %s ');
+        console.log('\r' + fmt, test.title);
+      } else {
+        var fmt = indent()
+          + color('checkmark', '  ✓')
+          + color('pass', ' %s ')
+          + color(test.speed, '(%dms)');
+        console.log('\r' + fmt, test.title, test.duration);
+      }
+    });
+  
+    runner.on('fail', function(test, err){
+      console.log('\r' + indent() + color('fail', '  %d) %s'), n++, test.title);
+    });
+  
+    runner.on('end', self.epilogue.bind(self));
+  }
+  
+  /**
+   * Inherit from `Base.prototype`.
+   */
+  
+  Spec.prototype.__proto__ = Base.prototype;
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_tap.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_tap.js.html new file mode 100644 index 0000000..f88d1f1 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_reporters_tap.js.html @@ -0,0 +1,245 @@ + + + + + + /Users/itay/Work/mocha/lib/reporters/tap.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/reporters/tap.js : 78%

+
+ 64 lines | + 50 run | + 14 missing | + 0 partial | + 25 blocks | + 2 blocks run | + 23 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Base = require('./base')
+    , cursor = Base.cursor
+    , color = Base.color;
+  
+  /**
+   * Expose `TAP`.
+   */
+  
+  exports = module.exports = TAP;
+  
+  /**
+   * Initialize a new `TAP` reporter.
+   *
+   * @param {Runner} runner
+   * @api public
+   */
+  
+  function TAP(runner) {
+    Base.call(this, runner);
+  
+    var self = this
+      , stats = this.stats
+      , total = runner.total
+      , n = 1;
+  
+    runner.on('start', function(){
+      console.log('%d..%d', 1, total);
+    });
+  
+    runner.on('test end', function(){
+      ++n;
+    });
+  
+    runner.on('pending', function(test){
+      console.log('ok %d %s # SKIP -', n, title(test));
+    });
+  
+    runner.on('pass', function(test){
+      console.log('ok %d %s', n, title(test));
+    });
+  
+    runner.on('fail', function(test, err){
+      console.log('not ok %d %s', n, title(test));
+      console.log(err.stack.replace(/^/gm, '  '));
+    });
+  }
+  
+  /**
+   * Return a TAP-safe title of `test`
+   *
+   * @param {Object} test
+   * @return {String}
+   * @api private
+   */
+  
+  function title(test) {
+    return test.fullTitle().replace(/#/g, '');
+  }
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_runnable.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_runnable.js.html new file mode 100644 index 0000000..bbd27c8 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_runnable.js.html @@ -0,0 +1,338 @@ + + + + + + /Users/itay/Work/mocha/lib/runnable.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/runnable.js : 77%

+
+ 157 lines | + 121 run | + 36 missing | + 0 partial | + 45 blocks | + 2 blocks run | + 43 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var EventEmitter = require('events').EventEmitter
+    , debug = require('debug')('runnable');
+  
+  /**
+   * Expose `Runnable`.
+   */
+  
+  module.exports = Runnable;
+  
+  /**
+   * Initialize a new `Runnable` with the given `title` and callback `fn`.
+   *
+   * @param {String} title
+   * @param {Function} fn
+   * @api private
+   */
+  
+  function Runnable(title, fn) {
+    this.title = title;
+    this.fn = fn;
+    this.async = fn && fn.length;
+    this.sync = ! this.async;
+    this._timeout = 2000;
+  }
+  
+  /**
+   * Inherit from `EventEmitter.prototype`.
+   */
+  
+  Runnable.prototype.__proto__ = EventEmitter.prototype;
+  
+  /**
+   * Set & get timeout `ms`.
+   *
+   * @param {Number} ms
+   * @return {Runnable|Number} ms or self
+   * @api private
+   */
+  
+  Runnable.prototype.timeout = function(ms){
+    if (0 == arguments.length) return this._timeout;
+    debug('timeout %d', ms);
+    this._timeout = ms;
+    if (this.timer) this.resetTimeout();
+    return this;
+  };
+  
+  /**
+   * Return the full title generated by recursively
+   * concatenating the parent's full title.
+   *
+   * @return {String}
+   * @api public
+   */
+  
+  Runnable.prototype.fullTitle = function(){
+    return this.parent.fullTitle() + ' ' + this.title;
+  };
+  
+  /**
+   * Clear the timeout.
+   *
+   * @api private
+   */
+  
+  Runnable.prototype.clearTimeout = function(){
+    clearTimeout(this.timer);
+  };
+  
+  /**
+   * Reset the timeout.
+   *
+   * @api private
+   */
+  
+  Runnable.prototype.resetTimeout = function(){
+    var self = this
+      , ms = this.timeout();
+  
+    this.clearTimeout();
+    if (ms) {
+      this.timer = setTimeout(function(){
+        self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
+      }, ms);
+    }
+  };
+  
+  /**
+   * Run the test and invoke `fn(err)`.
+   *
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runnable.prototype.run = function(fn){
+    var self = this
+      , ms = this.timeout()
+      , start = new Date
+      , finished
+      , emitted;
+  
+    // timeout
+    if (this.async) {
+      if (ms) {
+        this.timer = setTimeout(function(){
+          done(new Error('timeout of ' + ms + 'ms exceeded'));
+        }, ms);
+      }
+    }
+  
+    // called multiple times
+    function multiple() {
+      if (emitted) return;
+      emitted = true;
+      self.emit('error', new Error('done() called multiple times'));
+    }
+  
+    // finished
+    function done(err) {
+      if (finished) return multiple();
+      self.clearTimeout();
+      self.duration = new Date - start;
+      finished = true;
+      fn(err);
+    }
+  
+    // for .resetTimeout()
+    this.callback = done;
+  
+    // async
+    if (this.async) {
+      try {
+        this.fn(function(err){
+          if (err instanceof Error) return done(err);
+          done();
+        });
+      } catch (err) {
+        done(err);
+      }
+      return;
+    }
+    
+    // sync
+    try {
+      if (!this.pending) this.fn();
+      this.duration = new Date - start;
+      fn();
+    } catch (err) {
+      fn(err);
+    }
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_runner.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_runner.js.html new file mode 100644 index 0000000..b5dd9d6 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_runner.js.html @@ -0,0 +1,596 @@ + + + + + + /Users/itay/Work/mocha/lib/runner.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/runner.js : 72%

+
+ 415 lines | + 301 run | + 114 missing | + 0 partial | + 158 blocks | + 2 blocks run | + 156 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var EventEmitter = require('events').EventEmitter
+    , debug = require('debug')('runner')
+    , Test = require('./test')
+    , utils = require('./utils')
+    , noop = function(){};
+  
+  /**
+   * Expose `Runner`.
+   */
+  
+  module.exports = Runner;
+  
+  /**
+   * Initialize a `Runner` for the given `suite`.
+   *
+   * Events:
+   *
+   *   - `start`  execution started
+   *   - `end`  execution complete
+   *   - `suite`  (suite) test suite execution started
+   *   - `suite end`  (suite) all tests (and sub-suites) have finished
+   *   - `test`  (test) test execution started
+   *   - `test end`  (test) test completed
+   *   - `hook`  (hook) hook execution started
+   *   - `hook end`  (hook) hook complete
+   *   - `pass`  (test) test passed
+   *   - `fail`  (test, err) test failed
+   *
+   * @api public
+   */
+  
+  function Runner(suite) {
+    var self = this;
+    this._globals = [];
+    this.suite = suite;
+    this.total = suite.total();
+    this.failures = 0;
+    this.on('test end', function(test){ self.checkGlobals(test); });
+    this.on('hook end', function(hook){ self.checkGlobals(hook); });
+    this.grep(/.*/);
+    this.globals(utils.keys(global).concat(['errno']));
+  }
+  
+  /**
+   * Inherit from `EventEmitter.prototype`.
+   */
+  
+  Runner.prototype.__proto__ = EventEmitter.prototype;
+  
+  /**
+   * Run tests with full titles matching `re`.
+   *
+   * @param {RegExp} re
+   * @return {Runner} for chaining
+   * @api public
+   */
+  
+  Runner.prototype.grep = function(re){
+    debug('grep %s', re);
+    this._grep = re;
+    return this;
+  };
+  
+  /**
+   * Allow the given `arr` of globals.
+   *
+   * @param {Array} arr
+   * @return {Runner} for chaining
+   * @api public
+   */
+  
+  Runner.prototype.globals = function(arr){
+    debug('globals %j', arr);
+    utils.forEach(arr, function(arr){
+      this._globals.push(arr);
+    }, this);
+    return this;
+  };
+  
+  /**
+   * Check for global variable leaks.
+   *
+   * @api private
+   */
+  
+  Runner.prototype.checkGlobals = function(test){
+    if (this.ignoreLeaks) return;
+  
+    var leaks = utils.filter(utils.keys(global), function(key){
+      return !~utils.indexOf(this._globals, key);
+    }, this);
+  
+    this._globals = this._globals.concat(leaks);
+  
+    if (leaks.length > 1) {
+      this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
+    } else if (leaks.length) {
+      this.fail(test, new Error('global leak detected: ' + leaks[0]));
+    }
+  };
+  
+  /**
+   * Fail the given `test`.
+   *
+   * @param {Test} test
+   * @param {Error} err
+   * @api private
+   */
+  
+  Runner.prototype.fail = function(test, err){
+    ++this.failures;
+    test.failed = true;
+    this.emit('fail', test, err);
+  };
+  
+  /**
+   * Fail the given `hook` with `err`.
+   *
+   * Hook failures (currently) hard-end due
+   * to that fact that a failing hook will
+   * surely cause subsequent tests to fail,
+   * causing jumbled reporting.
+   *
+   * @param {Hook} hook
+   * @param {Error} err
+   * @api private
+   */
+  
+  Runner.prototype.failHook = function(hook, err){
+    ++this.failures;
+    this.fail(hook, err);
+    this.emit('end');
+  };
+  
+  /**
+   * Run hook `name` callbacks and then invoke `fn()`.
+   *
+   * @param {String} name
+   * @param {Function} function
+   * @api private
+   */
+  
+  Runner.prototype.hook = function(name, fn){
+    var suite = this.suite
+      , hooks = suite['_' + name]
+      , ms = suite._timeout
+      , self = this
+      , timer;
+  
+    function next(i) {
+      var hook = hooks[i];
+      if (!hook) return fn();
+      self.currentRunnable = hook;
+  
+      self.emit('hook', hook);
+  
+      hook.on('error', function(err){
+        self.failHook(hook, err);
+      });
+  
+      hook.run(function(err){
+        hook.removeAllListeners('error');
+        if (err) return self.failHook(hook, err);
+        self.emit('hook end', hook);
+        next(++i);
+      });
+    }
+  
+    process.nextTick(function(){
+      next(0);
+    });
+  };
+  
+  /**
+   * Run hook `name` for the given array of `suites`
+   * in order, and callback `fn(err)`.
+   *
+   * @param {String} name
+   * @param {Array} suites
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.hooks = function(name, suites, fn){
+    var self = this
+      , orig = this.suite;
+  
+    function next(suite) {
+      self.suite = suite;
+  
+      if (!suite) {
+        self.suite = orig;
+        return fn();
+      }
+  
+      self.hook(name, function(err){
+        if (err) {
+          self.suite = orig;
+          return fn(err);
+        }
+  
+        next(suites.pop());
+      });
+    }
+  
+    next(suites.pop());
+  };
+  
+  /**
+   * Run hooks from the top level down.
+   *
+   * @param {String} name
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.hookUp = function(name, fn){
+    var suites = [this.suite].concat(this.parents()).reverse();
+    this.hooks(name, suites, fn);
+  };
+  
+  /**
+   * Run hooks from the bottom up.
+   *
+   * @param {String} name
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.hookDown = function(name, fn){
+    var suites = [this.suite].concat(this.parents());
+    this.hooks(name, suites, fn);
+  };
+  
+  /**
+   * Return an array of parent Suites from
+   * closest to furthest.
+   *
+   * @return {Array}
+   * @api private
+   */
+  
+  Runner.prototype.parents = function(){
+    var suite = this.suite
+      , suites = [];
+    while (suite = suite.parent) suites.push(suite);
+    return suites;
+  };
+  
+  /**
+   * Run the current test and callback `fn(err)`.
+   *
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.runTest = function(fn){
+    var test = this.test
+      , self = this;
+  
+    try {
+      test.on('error', function(err){
+        self.fail(test, err);
+      });
+      test.run(fn);
+    } catch (err) {
+      fn(err);
+    }
+  };
+  
+  /**
+   * Run tests in the given `suite` and invoke
+   * the callback `fn()` when complete.
+   *
+   * @param {Suite} suite
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.runTests = function(suite, fn){
+    var self = this
+      , tests = suite.tests
+      , test;
+  
+    function next(err) {
+      // next test
+      test = tests.shift();
+  
+      // all done
+      if (!test) return fn();
+  
+      // grep
+      if (!self._grep.test(test.fullTitle())) return next();
+  
+      // pending
+      if (test.pending) {
+        self.emit('pending', test);
+        self.emit('test end', test);
+        return next();
+      }
+  
+      // execute test and hook(s)
+      self.emit('test', self.test = self.currentRunnable = test);
+      self.hookDown('beforeEach', function(){
+        self.runTest(function(err){
+          if (err) {
+            self.fail(test, err);
+            self.emit('test end', test);
+            return self.hookUp('afterEach', next);
+          }
+  
+          test.passed = true;
+          self.emit('pass', test);
+          self.emit('test end', test);
+          self.hookUp('afterEach', next);
+        });
+      });
+    }
+  
+    this.next = next;
+    next();
+  };
+  
+  /**
+   * Run the given `suite` and invoke the
+   * callback `fn()` when complete.
+   *
+   * @param {Suite} suite
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Runner.prototype.runSuite = function(suite, fn){
+    var self = this
+      , i = 0;
+  
+    debug('run suite %s', suite.fullTitle());
+    this.emit('suite', this.suite = suite);
+  
+    function next() {
+      var curr = suite.suites[i++];
+      if (!curr) return done();
+      self.runSuite(curr, next);
+    }
+  
+    function done() {
+      self.suite = suite;
+      self.hook('afterAll', function(){
+        self.emit('suite end', suite);
+        fn();
+      });
+    }
+  
+    this.hook('beforeAll', function(){
+      self.runTests(suite, next);
+    });
+  };
+  
+  /**
+   * Run the root suite and invoke `fn(failures)`
+   * on completion.
+   *
+   * @param {Function} fn
+   * @return {Runner} for chaining
+   * @api public
+   */
+  
+  Runner.prototype.run = function(fn){
+    var self = this
+      , fn = fn || function(){};
+  
+    debug('start');
+  
+    // callback
+    self.on('end', function(){
+      debug('end');
+      process.removeListener('uncaughtException', uncaught);
+      fn(self.failures);
+    });
+  
+    // run suites
+    this.emit('start');
+    this.runSuite(this.suite, function(){
+      debug('finished running');
+      self.emit('end');
+    });
+  
+    // uncaught exception
+    function uncaught(err){
+      var runnable = self.currentRunnable;
+      debug('uncaught exception');
+      runnable.clearTimeout();
+      err.uncaught = true;
+      self.fail(runnable, err);
+  
+      // recover from test
+      if ('test' == runnable.type) {
+        self.emit('test end', runnable);
+        self.hookUp('afterEach', self.next);
+      // bail on hooks
+      } else {
+        self.emit('end');
+      }
+    }
+  
+    process.on('uncaughtException', uncaught);
+  
+    return this;
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_suite.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_suite.js.html new file mode 100644 index 0000000..05b43ec --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_suite.js.html @@ -0,0 +1,402 @@ + + + + + + /Users/itay/Work/mocha/lib/suite.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/suite.js : 81%

+
+ 221 lines | + 181 run | + 40 missing | + 1 partial | + 53 blocks | + 8 blocks run | + 45 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var EventEmitter = require('events').EventEmitter
+    , debug = require('debug')('suite')
+    , utils = require('./utils')
+    , Hook = require('./hook');
+  
+  /**
+   * Expose `Suite`.
+   */
+  
+  exports = module.exports = Suite;
+  
+  /**
+   * Create a new `Suite` with the given `title`
+   * and parent `Suite`. When a suite with the
+   * same title is already present, that suite
+   * is returned to provide nicer reporter
+   * and more flexible meta-testing.
+   *
+   * @param {Suite} parent
+   * @param {String} title
+   * @return {Suite}
+   * @api public
+   */
+  
+  exports.create = function(parent, title){
+    var suite = new Suite(title);
+    suite.parent = parent;
+    title = suite.fullTitle();
+    parent.addSuite(suite);
+    return suite;
+  };
+  
+  /**
+   * Initialize a new `Suite` with the given `title`.
+   *
+   * @param {String} title
+   * @api private
+   */
+  
+  function Suite(title) {
+    this.title = title;
+    this.suites = [];
+    this.tests = [];
+    this._beforeEach = [];
+    this._beforeAll = [];
+    this._afterEach = [];
+    this._afterAll = [];
+    this.root = !title;
+    this._timeout = 2000;
+  }
+  
+  /**
+   * Inherit from `EventEmitter.prototype`.
+   */
+  
+  Suite.prototype.__proto__ = EventEmitter.prototype;
+  
+  /**
+   * Return a clone of this `Suite`.
+   *
+   * @return {Suite}
+   * @api private
+   */
+  
+  Suite.prototype.clone = function(){
+    var suite = new Suite(this.title);
+    debug('clone');
+    suite.timeout(this.timeout());
+    return suite;
+  };
+  
+  /**
+   * Set timeout `ms` or short-hand such as "2s".
+   *
+   * @param {Number|String} ms
+   * @return {Suite|Number} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.timeout = function(ms){
+    if (0 == arguments.length) return this._timeout;
+    if (String(ms).match(/s$/))   ms = parseFloat(ms) * 1000;  parseFloat(ms) * 1000;
+    debug('timeout %d', ms);
+    this._timeout = parseInt(ms, 10);
+    return this;
+  };
+  
+  /**
+   * Run `fn(test[, done])` before running tests.
+   *
+   * @param {Function} fn
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.beforeAll = function(fn){
+    var hook = new Hook('"before all" hook', fn);
+    hook.parent = this;
+    hook.timeout(this.timeout());
+    this._beforeAll.push(hook);
+    this.emit('beforeAll', hook);
+    return this;
+  };
+  
+  /**
+   * Run `fn(test[, done])` after running tests.
+   *
+   * @param {Function} fn
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.afterAll = function(fn){
+    var hook = new Hook('"after all" hook', fn);
+    hook.parent = this;
+    hook.timeout(this.timeout());
+    this._afterAll.push(hook);
+    this.emit('afterAll', hook);
+    return this;
+  };
+  
+  /**
+   * Run `fn(test[, done])` before each test case.
+   *
+   * @param {Function} fn
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.beforeEach = function(fn){
+    var hook = new Hook('"before each" hook', fn);
+    hook.parent = this;
+    hook.timeout(this.timeout());
+    this._beforeEach.push(hook);
+    this.emit('beforeEach', hook);
+    return this;
+  };
+  
+  /**
+   * Run `fn(test[, done])` after each test case.
+   *
+   * @param {Function} fn
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.afterEach = function(fn){
+    var hook = new Hook('"after each" hook', fn);
+    hook.parent = this;
+    hook.timeout(this.timeout());
+    this._afterEach.push(hook);
+    this.emit('afterEach', hook);
+    return this;
+  };
+  
+  /**
+   * Add a test `suite`.
+   *
+   * @param {Suite} suite
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.addSuite = function(suite){
+    suite.parent = this;
+    suite.timeout(this.timeout());
+    this.suites.push(suite);
+    this.emit('suite', suite);
+    return this;
+  };
+  
+  /**
+   * Add a `test` to this suite.
+   *
+   * @param {Test} test
+   * @return {Suite} for chaining
+   * @api private
+   */
+  
+  Suite.prototype.addTest = function(test){
+    test.parent = this;
+    test.timeout(this.timeout());
+    this.tests.push(test);
+    this.emit('test', test);
+    return this;
+  };
+  
+  /**
+   * Return the full title generated by recursively
+   * concatenating the parent's full title.
+   *
+   * @return {String}
+   * @api public
+   */
+  
+  Suite.prototype.fullTitle = function(){
+    if (this.parent) {
+      var full = this.parent.fullTitle();
+      if (full) return full + ' ' + this.title;
+    }
+    return this.title;
+  };
+  
+  /**
+   * Return the total number of tests.
+   *
+   * @return {Number}
+   * @api public
+   */
+  
+  Suite.prototype.total = function(){
+    return utils.reduce(this.suites, function(sum, suite){
+      return sum + suite.total();
+    }, 0) + this.tests.length;
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_test.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_test.js.html new file mode 100644 index 0000000..55c9d9f --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_test.js.html @@ -0,0 +1,214 @@ + + + + + + /Users/itay/Work/mocha/lib/test.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/test.js : 90%

+
+ 33 lines | + 30 run | + 3 missing | + 0 partial | + 4 blocks | + 2 blocks run | + 2 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var Runnable = require('./runnable');
+  
+  /**
+   * Expose `Test`.
+   */
+  
+  module.exports = Test;
+  
+  /**
+   * Initialize a new `Test` with the given `title` and callback `fn`.
+   *
+   * @param {String} title
+   * @param {Function} fn
+   * @api private
+   */
+  
+  function Test(title, fn) {
+    Runnable.call(this, title, fn);
+    this.pending = !fn;
+    this.type = 'test';
+  }
+  
+  /**
+   * Inherit from `Runnable.prototype`.
+   */
+  
+  Test.prototype.__proto__ = Runnable.prototype;
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_utils.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_utils.js.html new file mode 100644 index 0000000..bd306c6 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_utils.js.html @@ -0,0 +1,291 @@ + + + + + + /Users/itay/Work/mocha/lib/utils.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/utils.js : 84%

+
+ 110 lines | + 93 run | + 17 missing | + 0 partial | + 20 blocks | + 1 blocks run | + 19 blocks missing +
+
+
+
+  
+  /**
+   * Escape special characters in the given string of html.
+   *
+   * @param  {String} html
+   * @return {String}
+   * @api private
+   */
+  
+  exports.escape = function(html) {
+    return String(html)
+      .replace(/&/g, '&')
+      .replace(/"/g, '"')
+      .replace(/</g, '<')
+      .replace(/>/g, '>');
+  };
+  
+  /**
+   * Array#forEach (<=IE8)
+   *
+   * @param {Array} array
+   * @param {Function} fn
+   * @param {Object} scope
+   * @api private
+   */
+  
+  exports.forEach = function(arr, fn, scope) {
+    for (var i = 0, l = arr.length; i < l; i++)
+      fn.call(scope, arr[i], i);
+  };
+  
+  /**
+   * Array#indexOf (<=IE8)
+   *
+   * @parma {Array} arr
+   * @param {Object} obj to find index of
+   * @param {Number} start
+   * @api private
+   */
+  
+  exports.indexOf = function (arr, obj, start) {
+    for (var i = start || 0, l = arr.length; i < l; i++) {
+      if (arr[i] === obj)
+        return i;
+    }
+    return -1;
+  };
+  
+  /**
+   * Array#reduce (<=IE8)
+   * 
+   * @param {Array} array
+   * @param {Function} fn
+   * @param {Object} initial value
+   * @param {Object} scope
+   * @api private
+   */
+  
+  exports.reduce = function(arr, fn, val, scope) {
+    var rval = val;
+  
+    for (var i = 0, l = arr.length; i < l; i++) {
+      rval = fn.call(scope, rval, arr[i], i, arr);
+    }
+  
+    return rval;
+  };
+  
+  /**
+   * Array#filter (<=IE8)
+   *
+   * @param {Array} array
+   * @param {Function} fn
+   * @param {Object} scope
+   * @api private
+   */
+  
+  exports.filter = function(arr, fn, scope) {
+    var ret = [];
+  
+    for (var i = 0, l = arr.length; i < l; i++) {
+      var val = arr[i];
+      if (fn.call(scope, val, i, arr))
+        ret.push(val);
+    }
+  
+    return ret;
+  };
+  
+  /**
+   * Object.keys (<=IE8)
+   *
+   * @param {Object} obj
+   * @return {Array} keys
+   * @api private
+   */
+  
+  exports.keys = Object.keys || function(obj) {
+    var keys = []
+      , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
+  
+    for (var i in obj) {
+      if (has.call(obj, i)) {
+        keys.push(i);
+      }
+    }
+  
+    return keys;
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_lib_watch.js.html b/mocha/cover_html/_Users_itay_Work_mocha_lib_watch.js.html new file mode 100644 index 0000000..11f4fb6 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_lib_watch.js.html @@ -0,0 +1,198 @@ + + + + + + /Users/itay/Work/mocha/lib/watch.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/lib/watch.js : 70%

+
+ 17 lines | + 12 run | + 5 missing | + 0 partial | + 9 blocks | + 2 blocks run | + 7 blocks missing +
+
+
+
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var fs = require('fs')
+    , debug = require('debug')('watch');
+  
+  module.exports = function(paths, fn){
+    var options = { interval: 100 };
+    paths.forEach(function(path){
+      debug('watch %s', path);
+      fs.watchFile(path, options, function(curr, prev){
+        if (prev.mtime < curr.mtime) fn(path);
+      });
+    });
+  };
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_index.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_index.js.html new file mode 100644 index 0000000..11361b9 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_index.js.html @@ -0,0 +1,183 @@ + + + + + + /Users/itay/Work/mocha/node_modules/commander/index.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/commander/index.js : 100%

+
+ 2 lines | + 2 run | + 0 missing | + 0 partial | + 2 blocks | + 2 blocks run | + 0 blocks missing +
+
+
+
+  
+  module.exports = require('./lib/commander');
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_lib_commander.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_lib_commander.js.html new file mode 100644 index 0000000..dc1cf0d --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_commander_lib_commander.js.html @@ -0,0 +1,1090 @@ + + + + + + /Users/itay/Work/mocha/node_modules/commander/lib/commander.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/commander/lib/commander.js : 85%

+
+ 909 lines | + 778 run | + 131 missing | + 5 partial | + 259 blocks | + 72 blocks run | + 187 blocks missing +
+
+
+
+  /*!
+   * commander
+   * Copyright(c) 2011 TJ Holowaychuk 
+   * MIT Licensed
+   */
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var EventEmitter = require('events').EventEmitter
+    , path = require('path')
+    , tty = require('tty')
+    , basename = path.basename;
+  
+  /**
+   * Expose the root command.
+   */
+  
+  exports = module.exports = new Command;
+  
+  /**
+   * Expose `Command`.
+   */
+  
+  exports.Command = Command;
+  
+  /**
+   * Expose `Option`.
+   */
+  
+  exports.Option = Option;
+  
+  /**
+   * Initialize a new `Option` with the given `flags` and `description`.
+   *
+   * @param {String} flags
+   * @param {String} description
+   * @api public
+   */
+  
+  function Option(flags, description) {
+    this.flags = flags;
+    this.required = ~flags.indexOf('<');
+    this.optional = ~flags.indexOf('[');
+    this.bool = !~flags.indexOf('-no-');
+    flags = flags.split(/[ ,|]+/);
+    if (flags.length > 1 && !  /^[[<]/.test(flags[1])) this.short = flags.shift();
+    this.long = flags.shift();
+    this.description = description;
+  }
+  
+  /**
+   * Return option name.
+   *
+   * @return {String}
+   * @api private
+   */
+  
+  Option.prototype.name = function(){
+    return this.long
+      .replace('--', '')
+      .replace('no-', '');
+  };
+  
+  /**
+   * Check if `arg` matches the short or long flag.
+   *
+   * @param {String} arg
+   * @return {Boolean}
+   * @api private
+   */
+  
+  Option.prototype.is = function(arg){
+    return arg == this.short
+      || arg == this.long;
+  };
+  
+  /**
+   * Initialize a new `Command`.
+   *
+   * @param {String} name
+   * @api public
+   */
+  
+  function Command(name) {
+    this.commands = [];
+    this.options = [];
+    this.args = [];
+    this.name = name;
+  }
+  
+  /**
+   * Inherit from `EventEmitter.prototype`.
+   */
+  
+  Command.prototype.__proto__ = EventEmitter.prototype;
+  
+  /**
+   * Add command `name`.
+   *
+   * The `.action()` callback is invoked when the
+   * command `name` is specified via __ARGV__,
+   * and the remaining arguments are applied to the
+   * function for access.
+   *
+   * When the `name` is "*" an un-matched command
+   * will be passed as the first arg, followed by
+   * the rest of __ARGV__ remaining.
+   *
+   * Examples:
+   *
+   *      program
+   *        .version('0.0.1')
+   *        .option('-C, --chdir ', 'change the working directory')
+   *        .option('-c, --config ', 'set config path. defaults to ./deploy.conf')
+   *        .option('-T, --no-tests', 'ignore test hook')
+   *     
+   *      program
+   *        .command('setup')
+   *        .description('run remote setup commands')
+   *        .action(function(){
+   *          console.log('setup');
+   *        });
+   *     
+   *      program
+   *        .command('exec ')
+   *        .description('run the given remote command')
+   *        .action(function(cmd){
+   *          console.log('exec "%s"', cmd);
+   *        });
+   *     
+   *      program
+   *        .command('*')
+   *        .description('deploy the given env')
+   *        .action(function(env){
+   *          console.log('deploying "%s"', env);
+   *        });
+   *     
+   *      program.parse(process.argv);
+    *
+   * @param {String} name
+   * @return {Command} the new command
+   * @api public
+   */
+  
+  Command.prototype.command = function(name){
+    var args = name.split(/ +/);
+    var cmd = new Command(args.shift());
+    this.commands.push(cmd);
+    cmd.parseExpectedArgs(args);
+    cmd.parent = this;
+    return cmd;
+  };
+  
+  /**
+   * Parse expected `args`.
+   *
+   * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
+   *
+   * @param {Array} args
+   * @return {Command} for chaining
+   * @api public
+   */
+  
+  Command.prototype.parseExpectedArgs = function(args){
+    if (!args.length) return;
+    var self = this;
+    args.forEach(function(arg){
+      switch (arg[0]) {
+        case '<':
+          self.args.push({ required: true, name: arg.slice(1, -1) });
+          break;
+        case '[':
+          self.args.push({ required: false, name: arg.slice(1, -1) });
+          break;
+      }
+    });
+    return this;
+  };
+  
+  /**
+   * Register callback `fn` for the command.
+   *
+   * Examples:
+   *
+   *      program
+   *        .command('help')
+   *        .description('display verbose help')
+   *        .action(function(){
+   *           // output help here
+   *        });
+   *
+   * @param {Function} fn
+   * @return {Command} for chaining
+   * @api public
+   */
+  
+  Command.prototype.action = function(fn){
+    var self = this;
+    this.parent.on(this.name, function(args){
+      self.args.forEach(function(arg, i){
+        if (arg.required && null == args[i]) {
+          self.missingArgument(arg.name);
+        }
+      });
+      fn.apply(this, args);
+    });
+    return this;
+  };
+  
+  /**
+   * Define option with `flags`, `description` and optional
+   * coercion `fn`. 
+   *
+   * The `flags` string should contain both the short and long flags,
+   * separated by comma, a pipe or space. The following are all valid
+   * all will output this way when `--help` is used.
+   *
+   *    "-p, --pepper"
+   *    "-p|--pepper"
+   *    "-p --pepper"
+   *
+   * Examples:
+   *
+   *     // simple boolean defaulting to false
+   *     program.option('-p, --pepper', 'add pepper');
+   *
+   *     --pepper
+   *     program.pepper
+   *     // => Boolean
+   *
+   *     // simple boolean defaulting to false
+   *     program.option('-C, --no-cheese', 'remove cheese');
+   *
+   *     program.cheese
+   *     // => true
+   *
+   *     --no-cheese
+   *     program.cheese
+   *     // => true
+   *
+   *     // required argument
+   *     program.option('-C, --chdir ', 'change the working directory');
+   *
+   *     --chdir /tmp
+   *     program.chdir
+   *     // => "/tmp"
+   *
+   *     // optional argument
+   *     program.option('-c, --cheese [type]', 'add cheese [marble]');
+   *
+   * @param {String} flags
+   * @param {String} description
+   * @param {Function|Mixed} fn or default
+   * @param {Mixed} defaultValue
+   * @return {Command} for chaining
+   * @api public
+   */
+  
+  Command.prototype.option = function(flags, description, fn, defaultValue){
+    var self = this
+      , option = new Option(flags, description)
+      , oname = option.name()
+      , name = camelcase(oname);
+  
+    // default as 3rd arg
+    if ('function' != typeof fn) defaultValue = fn, fn = null;
+  
+    // preassign default value only for --no-*, [optional], or 
+    if (false == option.bool || option.optional || option.required) {
+      // when --no-* we make sure default is true
+      if (false == option.bool) defaultValue = true;
+      // preassign only if we have a default
+      if (undefined !== defaultValue) self[name] = defaultValue;
+    }
+  
+    // register the option
+    this.options.push(option);
+  
+    // when it's passed assign the value
+    // and conditionally invoke the callback
+    this.on(oname, function(val){
+      // coercion
+      if (null != val && fn) val = fn(val);
+  
+      // unassigned or bool
+      if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
+        // if no value, bool true, and we have a default, then use it!
+        if (null == val) {
+          self[name] = option.bool
+            ? defaultValue || true
+            : false;
+        } else {
+          self[name] = val;
+        }
+      } else if (null !== val) {
+        // reassign
+        self[name] = val;
+      }
+    });
+  
+    return this;
+  };
+  
+  /**
+   * Parse `argv`, settings options and invoking commands when defined.
+   *
+   * @param {Array} argv
+   * @return {Command} for chaining
+   * @api public
+   */
+  
+  Command.prototype.parse = function(argv){
+    // store raw args
+    this.rawArgs = argv;
+  
+    // guess name
+    if (!this.name) this.name = basename(argv[1]);
+  
+    // process argv
+    this.args = this.parseOptions(this.normalize(argv));
+    return this.parseArgs(this.args);
+  };
+  
+  /**
+   * Normalize `args`, splitting joined short flags. For example
+   * the arg "-abc" is equivalent to "-a -b -c".
+   *
+   * @param {Array} args
+   * @return {Array}
+   * @api private
+   */
+  
+  Command.prototype.normalize = function(args){
+    var ret = []
+      , arg;
+  
+    for (var i = 0, len = args.length; i < len; ++i) {
+      arg = args[i];
+      if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
+        arg.slice(1).split('').forEach(function(c){
+          ret.push('-' + c);
+        });
+      } else {
+        ret.push(arg);
+      }
+    }
+  
+    return ret;
+  };
+  
+  /**
+   * Parse command `args`.
+   *
+   * When listener(s) are available those
+   * callbacks are invoked, otherwise the "*"
+   * event is emitted and those actions are invoked.
+   *
+   * @param {Array} args
+   * @return {Command} for chaining
+   * @api private
+   */
+  
+  Command.prototype.parseArgs = function(args){
+    var cmds = this.commands
+      , len = cmds.length
+      , name;
+  
+    if (args.length) {
+      name = args[0];
+      if (this.listeners(name).length) {
+        this.emit(args.shift(), args);
+      } else {
+        this.emit('*', args);
+      }
+    }
+  
+    return this;
+  };
+  
+  /**
+   * Return an option matching `arg` if any.
+   *
+   * @param {String} arg
+   * @return {Option}
+   * @api private
+   */
+  
+  Command.prototype.optionFor = function(arg){
+    for (var i = 0, len = this.options.length; i < len; ++i) {
+      if (this.options[i].is(arg)) {
+        return this.options[i];
+      }
+    }
+  };
+  
+  /**
+   * Parse options from `argv` returning `argv`
+   * void of these options.
+   *
+   * @param {Array} argv
+   * @return {Array}
+   * @api public
+   */
+  
+  Command.prototype.parseOptions = function(argv){
+    var args = []
+      , argv = argv.slice(2)
+      , len = argv.length
+      , option
+      , arg;
+  
+    // parse options
+    for (var i = 0; i < len; ++i) {
+      arg = argv[i];
+      option = this.optionFor(arg);
+  
+      // option is defined
+      if (option) {
+        // requires arg
+        if (option.required) {
+          arg = argv[++i];
+          if (null == arg) return   this.optionMissingArgument(option);
+          if ('-' == arg[0]) return   this.optionMissingArgument(option, arg);
+          this.emit(option.name(), arg);
+        // optional arg
+        } else if (option.optional) {
+          arg = argv[i+1];
+          if (null == arg || '-' == arg[0]) {
+            arg = null;
+          } else {
+            ++i;
+          }
+          this.emit(option.name(), arg);
+        // bool
+        } else {
+          this.emit(option.name());
+        }
+        continue;
+      }
+      
+      // looks like an option
+      if (arg.length > 1 && '-' == arg[0]) {
+        this.unknownOption(arg);
+      }
+      
+      // arg
+      args.push(arg);
+    }
+  
+    return args;
+  };
+  
+  /**
+   * Argument `name` is missing.
+   *
+   * @param {String} name
+   * @api private
+   */
+  
+  Command.prototype.missingArgument = function(name){
+    console.error();
+    console.error("  error: missing required argument `%s'", name);
+    console.error();
+    process.exit(1);
+  };
+  
+  /**
+   * `Option` is missing an argument, but received `flag` or nothing.
+   *
+   * @param {String} option
+   * @param {String} flag
+   * @api private
+   */
+  
+  Command.prototype.optionMissingArgument = function(option, flag){
+    console.error();
+    if (flag) {
+      console.error("  error: option `%s' argument missing, got `%s'", option.flags, flag);
+    } else {
+      console.error("  error: option `%s' argument missing", option.flags);
+    }
+    console.error();
+    process.exit(1);
+  };
+  
+  /**
+   * Unknown option `flag`.
+   *
+   * @param {String} flag
+   * @api private
+   */
+  
+  Command.prototype.unknownOption = function(flag){
+    console.error();
+    console.error("  error: unknown option `%s'", flag);
+    console.error();
+    process.exit(1);
+  };
+  
+  /**
+   * Set the program version to `str`.
+   *
+   * This method auto-registers the "-V, --version" flag
+   * which will print the version number when passed.
+   *
+   * @param {String} str
+   * @param {String} flags
+   * @return {Command} for chaining
+   * @api public
+   */
+  
+  Command.prototype.version = function(str, flags){
+    if (0 == arguments.length) return this._version;
+    this._version = str;
+    flags = flags || '-V, --version';
+    this.option(flags, 'output the version number');
+    this.on('version', function(){
+      console.log(str);
+      process.exit(0);
+    });
+    return this;
+  };
+  
+  /**
+   * Set the description `str`.
+   *
+   * @param {String} str
+   * @return {String|Command}
+   * @api public
+   */
+  
+  Command.prototype.description = function(str){
+    if (0 == arguments.length) return this._description;
+    this._description = str;
+    return this;
+  };
+  
+  /**
+   * Set / get the command usage `str`.
+   *
+   * @param {String} str
+   * @return {String|Command}
+   * @api public
+   */
+  
+  Command.prototype.usage = function(str){
+    var usage = '[options'
+      + (this.commands.length ? '] [command' : '')
+      + ']';
+    if (0 == arguments.length) return   this._usage || usage;
+    this._usage = str;
+    return this;
+  };
+  
+  /**
+   * Return the largest option length.
+   *
+   * @return {Number}
+   * @api private
+   */
+  
+  Command.prototype.largestOptionLength = function(){
+    return this.options.reduce(function(max, option){
+      return Math.max(max, option.flags.length);
+    }, 0);
+  };
+  
+  /**
+   * Return help for options.
+   *
+   * @return {String}
+   * @api private
+   */
+  
+  Command.prototype.optionHelp = function(){
+    var width = this.largestOptionLength();
+    return this.options.map(function(option){
+      return pad(option.flags, width)
+        + '  ' + option.description;
+    }).join('\n');
+  };
+  
+  /**
+   * Return command help documentation.
+   *
+   * @return {String}
+   * @api private
+   */
+  
+  Command.prototype.commandHelp = function(){
+    if (!this.commands.length) return '';
+    return [
+        ''
+      , '  Commands:'
+      , ''
+      , this.commands.map(function(cmd){
+        var args = cmd.args.map(function(arg){
+          return arg.required
+            ? '<' + arg.name + '>'
+            : '[' + arg.name + ']';
+        }).join(' ');
+        return cmd.name + ' ' + args
+          + (cmd.description()
+            ? '\n' + cmd.description()
+            : '');
+      }).join('\n\n').replace(/^/gm, '    ')
+      , ''
+    ].join('\n');
+  };
+  
+  /**
+   * Return program help documentation.
+   *
+   * @return {String}
+   * @api private
+   */
+  
+  Command.prototype.helpInformation = function(){
+    return [
+        ''
+      , '  Usage: ' + this.name + ' ' + this.usage()
+      , '' + this.commandHelp()
+      , '  Options:'
+      , ''
+      , '' + this.optionHelp().replace(/^/gm, '    ')
+      , ''
+      , ''
+    ].join('\n');
+  };
+  
+  /**
+   * Prompt for a `Number`.
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Command.prototype.promptForNumber = function(str, fn){
+    this.promptSingleLine(str, function(val){
+      val = Number(val);
+      if (isNaN(val)) return program.promptForNumber(str + '(must be a number) ', fn);
+      fn(val);
+    });
+  };
+  
+  /**
+   * Prompt for a `Date`.
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Command.prototype.promptForDate = function(str, fn){
+    this.promptSingleLine(str, function(val){
+      val = new Date(val);
+      if (isNaN(val.getTime())) return program.promptForDate(str + '(must be a date) ', fn);
+      fn(val);
+    });
+  };
+  
+  /**
+   * Single-line prompt.
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Command.prototype.promptSingleLine = function(str, fn){
+    if ('function' == typeof arguments[2]) {
+      return this['promptFor' + (fn.name || fn)](str, arguments[2]);
+    }
+  
+    process.stdout.write(str);
+    process.stdin.setEncoding('utf8');
+    process.stdin.once('data', function(val){
+      fn(val);
+    }).resume();
+  };
+  
+  /**
+   * Multi-line prompt.
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api private
+   */
+  
+  Command.prototype.promptMultiLine = function(str, fn){
+    var buf = '';
+    console.log(str);
+    process.stdin.setEncoding('utf8');
+    process.stdin.on('data', function(val){
+      if ('\n' == val) {
+        process.stdin.removeAllListeners('data');
+        fn(buf);
+      } else {
+        buf += val;
+      }
+    }).resume();
+  };
+  
+  /**
+   * Prompt `str` and callback `fn(val)`
+   *
+   * Commander supports single-line and multi-line prompts.
+   * To issue a single-line prompt simply add white-space
+   * to the end of `str`, something like "name: ", whereas
+   * for a multi-line prompt omit this "description:".
+   *
+   *
+   * Examples:
+   *
+   *     program.prompt('Username: ', function(name){
+   *       console.log('hi %s', name);
+   *     });
+   *     
+   *     program.prompt('Description:', function(desc){
+   *       console.log('description was "%s"', desc.trim());
+   *     });
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api public
+   */
+  
+  Command.prototype.prompt = function(str, fn){
+    if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
+    this.promptMultiLine(str, fn);
+  };
+  
+  /**
+   * Prompt for password with `str`, `mask` char and callback `fn(val)`.
+   *
+   * The mask string defaults to '', aka no output is
+   * written while typing, you may want to use "*" etc.
+   *
+   * Examples:
+   *
+   *     program.password('Password: ', function(pass){
+   *       console.log('got "%s"', pass);
+   *       process.stdin.destroy();
+   *     });
+   *
+   *     program.password('Password: ', '*', function(pass){
+   *       console.log('got "%s"', pass);
+   *       process.stdin.destroy();
+   *     });
+   *
+   * @param {String} str
+   * @param {String} mask
+   * @param {Function} fn
+   * @api public
+   */
+  
+  Command.prototype.password = function(str, mask, fn){
+    var self = this
+      , buf = '';
+  
+    // default mask
+    if ('function' == typeof mask) {
+      fn = mask;
+      mask = '';
+    }
+  
+    tty.setRawMode(true);
+    process.stdout.write(str);
+  
+    // keypress
+    process.stdin.on('keypress', function(c, key){
+      if (key && 'enter' == key.name) {
+        console.log();
+        process.stdin.removeAllListeners('keypress');
+        tty.setRawMode(false);
+        if (!buf.trim().length) return self.password(str, mask, fn);
+        fn(buf);
+        return;
+      }
+  
+      if (key && key.ctrl && 'c' == key.name) {
+        console.log('%s', buf);
+        process.exit();
+      }
+  
+      process.stdout.write(mask);
+      buf += c;
+    }).resume();
+  };
+  
+  /**
+   * Confirmation prompt with `str` and callback `fn(bool)`
+   *
+   * Examples:
+   *
+   *      program.confirm('continue? ', function(ok){
+   *        console.log(' got %j', ok);
+   *        process.stdin.destroy();
+   *      });
+   *
+   * @param {String} str
+   * @param {Function} fn
+   * @api public
+   */
+  
+  
+  Command.prototype.confirm = function(str, fn){
+    var self = this;
+    this.prompt(str, function(ok){
+      if (!ok.trim()) {
+        return self.confirm(str, fn);
+      }
+      fn(parseBool(ok));
+    });
+  };
+  
+  /**
+   * Choice prompt with `list` of items and callback `fn(index, item)`
+   *
+   * Examples:
+   *
+   *      var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
+   *      
+   *      console.log('Choose the coolest pet:');
+   *      program.choose(list, function(i){
+   *        console.log('you chose %d "%s"', i, list[i]);
+   *        process.stdin.destroy();
+   *      });
+   *
+   * @param {Array} list
+   * @param {Function} fn
+   * @api public
+   */
+  
+  Command.prototype.choose = function(list, fn){
+    var self = this;
+  
+    list.forEach(function(item, i){
+      console.log('  %d) %s', i + 1, item);
+    });
+  
+    function again() {
+      self.prompt('  : ', function(val){
+        val = parseInt(val, 10) - 1;
+        if (null == list[val]) {
+          again();
+        } else {
+          fn(val, list[val]);
+        }
+      });
+    }
+  
+    again();
+  };
+  
+  /**
+   * Camel-case the given `flag`
+   *
+   * @param {String} flag
+   * @return {String}
+   * @api private
+   */
+  
+  function camelcase(flag) {
+    return flag.split('-').reduce(function(str, word){
+      return str +   word[0].toUpperCase() + word.slice(1);
+    });
+  }
+  
+  /**
+   * Parse a boolean `str`.
+   *
+   * @param {String} str
+   * @return {Boolean}
+   * @api private
+   */
+  
+  function parseBool(str) {
+    return /^y|yes|ok|true$/i.test(str);
+  }
+  
+  /**
+   * Pad `str` to `width`.
+   *
+   * @param {String} str
+   * @param {Number} width
+   * @return {String}
+   * @api private
+   */
+  
+  function pad(str, width) {
+    var len = Math.max(0, width - str.length);
+    return str + Array(len + 1).join(' ');
+  }
+  
+  /**
+   * Default -h, --help option.
+   */
+  
+  exports.option('-h, --help', 'output usage information');
+  exports.on('help', function(){
+    process.stdout.write(this.helpInformation());
+    exports.emit('--help');
+    process.exit(0);
+  });
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_index.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_index.js.html new file mode 100644 index 0000000..5d14c85 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_index.js.html @@ -0,0 +1,183 @@ + + + + + + /Users/itay/Work/mocha/node_modules/debug/index.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/debug/index.js : 100%

+
+ 2 lines | + 2 run | + 0 missing | + 0 partial | + 2 blocks | + 2 blocks run | + 0 blocks missing +
+
+
+
+  
+  module.exports = require('./lib/debug');
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_lib_debug.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_lib_debug.js.html new file mode 100644 index 0000000..ae7792d --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_debug_lib_debug.js.html @@ -0,0 +1,266 @@ + + + + + + /Users/itay/Work/mocha/node_modules/debug/lib/debug.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/debug/lib/debug.js : 92%

+
+ 85 lines | + 79 run | + 6 missing | + 0 partial | + 15 blocks | + 8 blocks run | + 7 blocks missing +
+
+
+
+  
+  /*!
+   * debug
+   * Copyright(c) 2011 TJ Holowaychuk 
+   * MIT Licensed
+   */
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var tty = require('tty');
+  
+  /**
+   * Expose `debug()` as the module.
+   */
+  
+  module.exports = debug;
+  
+  /**
+   * Library version.
+   */
+  
+  exports.version = '0.1.0';
+  
+  /**
+   * Enabled debuggers.
+   */
+  
+  var names = (process.env.DEBUG || '').split(/[\s,]+/);
+  
+  /**
+   * Colors.
+   */
+  
+  var colors = [6, 2, 3, 4, 5, 1];
+  
+  /**
+   * Previously assigned color.
+   */
+  
+  var prevColor = 0;
+  
+  /**
+   * Is stderr a TTY? Colored output is disabled when `true`.
+   */
+  
+  var isatty = tty.isatty(process.stderr.fd || 2);
+  
+  /**
+   * Select a color.
+   *
+   * @return {Number}
+   * @api private
+   */
+  
+  function color() {
+    return colors[prevColor++ % colors.length];
+  }
+  
+  /**
+   * Create a debugger with the given `name`.
+   *
+   * @param {String} name
+   * @return {Type}
+   * @api public
+   */
+  
+  function debug(name) {
+    if (!~names.indexOf(name)) return function(){};
+    var c = color();
+  
+    function colored(fmt) {
+      fmt = '  \033[3' + c + 'm' + name + '\033[90m ' + fmt + '\033[0m';
+      console.error.apply(this, arguments);
+    }
+  
+    function plain(fmt) {
+      fmt = '  ' + name + ' ' + fmt;
+      console.error.apply(this, arguments);
+    }
+  
+    return isatty ? colored : plain;
+  }
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_growl_lib_growl.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_growl_lib_growl.js.html new file mode 100644 index 0000000..478f502 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_growl_lib_growl.js.html @@ -0,0 +1,342 @@ + + + + + + /Users/itay/Work/mocha/node_modules/growl/lib/growl.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/growl/lib/growl.js : 81%

+
+ 161 lines | + 132 run | + 29 missing | + 0 partial | + 45 blocks | + 4 blocks run | + 41 blocks missing +
+
+
+
+  
+  // Growl - Copyright TJ Holowaychuk  (MIT Licensed)
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var exec = require('child_process').exec
+    , path = require('path')
+    , os = require('os')
+    , cmd;
+  
+  switch(os.type()) {
+    case 'Darwin':
+      cmd = {
+          type: "Darwin"
+        , pkg: "growlnotify"
+        , msg: '-m'
+        , sticky: '--sticky'
+        , priority: {
+              cmd: '--priority'
+            , range: [
+                -2
+              , -1
+              , 0
+              , 1
+              , 2
+              , "Very Low"
+              , "Moderate"
+              , "Normal"
+              , "High"
+              , "Emergency"
+            ]
+          }
+      };
+      break;
+    case 'Linux':
+      cmd = {
+          type: "Linux"
+        , pkg: "notify-send"
+        , msg: ''
+        , sticky: '-t 0'
+        , priority: {
+            cmd: '-u'
+          , range: [
+              "low"
+            , "normal"
+            , "critical"
+          ]
+        }
+      };
+      break;
+    default:
+      console.error('✗ node-growl only supports Darwin and Linux users');
+      process.exit(1);
+  }
+  
+  /**
+   * Expose `growl`.
+   */
+  
+  exports = module.exports = growl;
+  
+  /**
+   * Node-growl version.
+   */
+  
+  exports.version = '1.4.0'
+  
+  /**
+   * Send growl notification _msg_ with _options_.
+   *
+   * Options:
+   *
+   *  - title   Notification title
+   *  - sticky  Make the notification stick (defaults to false)
+   *  - priority  Specify an int or named key (default is 0)
+   *  - name    Application name (defaults to growlnotify)
+   *  - image
+   *    - path to an icon sets --iconpath
+   *    - path to an image sets --image
+   *    - capitalized word sets --appIcon
+   *    - filename uses extname as --icon
+   *    - otherwise treated as --icon
+   *
+   * Examples:
+   *
+   *   growl('New email')
+   *   growl('5 new emails', { title: 'Thunderbird' })
+   *   growl('Email sent', function(){
+   *     // ... notification sent
+   *   })
+   *
+   * @param {string} msg
+   * @param {object} options
+   * @param {function} fn
+   * @api public
+   */
+  
+  function growl(msg, options, fn) {
+    var image
+      , args = [cmd.pkg]
+      , options = options || {}
+      , fn = fn || function(){};
+  
+    // image
+    if (image = options.image) {
+      switch(cmd.type) {
+        case 'Darwin':
+          var flag, ext = path.extname(image).substr(1)
+          flag = flag || ext == 'icns' && 'iconpath'
+          flag = flag || /^[A-Z]/.test(image) && 'appIcon'
+          flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image'
+          flag = flag || ext && (image = ext) && 'icon'
+          flag = flag || 'icon'
+          args.push('--' + flag, image)
+          break;
+        case 'Linux':
+          args.push('-i ' + image);
+          break;
+      }
+    }
+  
+    // sticky
+    if (options.sticky) args.push(cmd.sticky);
+  
+    // priority
+    if (options.priority) {
+      var priority = options.priority + '';
+      var checkindexOf = cmd.priority.range.indexOf(priority);
+      if (~cmd.priority.range.indexOf(priority)) {
+        args.push(cmd.priority, options.priority);
+      }
+    }
+  
+    // name
+    if (options.name && cmd.type === "Darwin") {
+      args.push('--name', options.name);
+    }
+  
+    switch(cmd.type) {
+      case 'Darwin':
+        args.push(cmd.msg);
+        args.push('"' + msg + '"');
+        if (options.title) args.push(options.title);
+        break;
+      case 'Linux':
+        if (options.title) {
+          args.push("'" + options.title + "'");
+          args.push(cmd.msg);
+          args.push("'" + msg + "'");
+        } else {
+          args.push("'" + msg + "'");
+        }
+        break;
+    }
+  
+    // execute
+    exec(args.join(' '), fn);
+  };
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_eql.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_eql.js.html new file mode 100644 index 0000000..ab0688a --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_eql.js.html @@ -0,0 +1,273 @@ + + + + + + /Users/itay/Work/mocha/node_modules/should/lib/eql.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/should/lib/eql.js : 68%

+
+ 92 lines | + 63 run | + 29 missing | + 0 partial | + 38 blocks | + 1 blocks run | + 37 blocks missing +
+
+
+
+  
+  // Taken from node's assert module, because it sucks
+  // and exposes next to nothing useful.
+  
+  module.exports = _deepEqual;
+  
+  function _deepEqual(actual, expected) {
+    // 7.1. All identical values are equivalent, as determined by ===.
+    if (actual === expected) {
+      return true;
+  
+    } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
+      if (actual.length != expected.length) return false;
+  
+      for (var i = 0; i < actual.length; i++) {
+        if (actual[i] !== expected[i]) return false;
+      }
+  
+      return true;
+  
+    // 7.2. If the expected value is a Date object, the actual value is
+    // equivalent if it is also a Date object that refers to the same time.
+    } else if (actual instanceof Date && expected instanceof Date) {
+      return actual.getTime() === expected.getTime();
+  
+    // 7.3. Other pairs that do not both pass typeof value == "object",
+    // equivalence is determined by ==.
+    } else if (typeof actual != 'object' && typeof expected != 'object') {
+      return actual === expected;
+  
+    // 7.4. For all other Object pairs, including Array objects, equivalence is
+    // determined by having the same number of owned properties (as verified
+    // with Object.prototype.hasOwnProperty.call), the same set of keys
+    // (although not necessarily the same order), equivalent values for every
+    // corresponding key, and an identical "prototype" property. Note: this
+    // accounts for both named and indexed properties on Arrays.
+    } else {
+      return objEquiv(actual, expected);
+    }
+  }
+  
+  function isUndefinedOrNull (value) {
+    return value === null || value === undefined;
+  }
+  
+  function isArguments (object) {
+    return Object.prototype.toString.call(object) == '[object Arguments]';
+  }
+  
+  function objEquiv (a, b) {
+    if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
+      return false;
+    // an identical "prototype" property.
+    if (a.prototype !== b.prototype) return false;
+    //~~~I've managed to break Object.keys through screwy arguments passing.
+    //   Converting to array solves the problem.
+    if (isArguments(a)) {
+      if (!isArguments(b)) {
+        return false;
+      }
+      a = pSlice.call(a);
+      b = pSlice.call(b);
+      return _deepEqual(a, b);
+    }
+    try{
+      var ka = Object.keys(a),
+        kb = Object.keys(b),
+        key, i;
+    } catch (e) {//happens when one is a string literal and the other isn't
+      return false;
+    }
+    // having the same number of owned properties (keys incorporates hasOwnProperty)
+    if (ka.length != kb.length)
+      return false;
+    //the same set of keys (although not necessarily the same order),
+    ka.sort();
+    kb.sort();
+    //~~~cheap key test
+    for (i = ka.length - 1; i >= 0; i--) {
+      if (ka[i] != kb[i])
+        return false;
+    }
+    //equivalent values for every corresponding key, and
+    //~~~possibly expensive deep test
+    for (i = ka.length - 1; i >= 0; i--) {
+      key = ka[i];
+      if (!_deepEqual(a[key], b[key] ))
+         return false;
+    }
+    return true;
+  }
+  
+
+ « index | cover.io +
+ + diff --git a/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_should.js.html b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_should.js.html new file mode 100644 index 0000000..658fb55 --- /dev/null +++ b/mocha/cover_html/_Users_itay_Work_mocha_node_modules_should_lib_should.js.html @@ -0,0 +1,827 @@ + + + + + + /Users/itay/Work/mocha/node_modules/should/lib/should.js -- cover.io + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ « index +

Coverage for /Users/itay/Work/mocha/node_modules/should/lib/should.js : 78%

+
+ 646 lines | + 504 run | + 142 missing | + 0 partial | + 150 blocks | + 5 blocks run | + 145 blocks missing +
+
+
+
+  /*!
+   * Should
+   * Copyright(c) 2010 TJ Holowaychuk 
+   * MIT Licensed
+   */
+  
+  /**
+   * Module dependencies.
+   */
+  
+  var util = require('util')
+    , http = require('http')
+    , assert = require('assert')
+    , AssertionError = assert.AssertionError
+    , statusCodes = http.STATUS_CODES
+    , eql = require('./eql')
+    , i = util.inspect;
+  
+  /**
+   * Expose assert as should.
+   * 
+   * This allows you to do things like below
+   * without require()ing the assert module.
+   *
+   *    should.equal(foo.bar, undefined);
+   *
+   */
+  
+  exports = module.exports = assert;
+  
+  /**
+   * Library version.
+   */
+  
+  exports.version = '0.3.2';
+  
+  /**
+   * Assert _obj_ exists, with optional message.
+   *
+   * @param {Mixed} obj
+   * @param {String} msg
+   * @api public
+   */
+   
+  exports.exist = function(obj, msg){
+    if (null == obj) {
+      throw new AssertionError({
+          message: msg || ('expected ' + i(obj) + ' to exist')
+        , stackStartFunction: should.exist
+      });
+    }
+  };
+  
+  /**
+   * Asserts _obj_ does not exist, with optional message.
+   *
+   * @param {Mixed} obj
+   * @param {String} msg
+   * @api public
+   */
+  
+  exports.not = {};
+  exports.not.exist = function(obj, msg){
+    if (null != obj) {
+      throw new AssertionError({
+          message: msg || ('expected ' + i(obj) + ' to not exist')
+        , stackStartFunction: should.not.exist
+      });
+    }
+  };
+  
+  /**
+   * Expose api via `Object#should`.
+   *
+   * @api public
+   */
+  
+  Object.defineProperty(Object.prototype, 'should', {
+    set: function(){},
+    get: function(){
+      return new Assertion(this);
+    },
+    configurable: true
+  });
+  
+  /**
+   * Initialize a new `Assertion` with the given _obj_.
+   *
+   * @param {Mixed} obj
+   * @api private
+   */
+  
+  var Assertion = exports.Assertion = function Assertion(obj) {
+    this.obj = obj;
+  };
+  
+  /**
+   * Prototype.
+   */
+  
+  Assertion.prototype = {
+  
+    /**
+     * HACK: prevents double require() from failing.
+     */
+    
+    exports: exports,
+  
+    /**
+     * Assert _expr_ with the given _msg_ and _negatedMsg_.
+     *
+     * @param {Boolean} expr
+     * @param {String} msg
+     * @param {String} negatedMsg
+     * @api private
+     */
+  
+    assert: function(expr, msg, negatedMsg){
+      var msg = this.negate ? negatedMsg : msg
+        , ok = this.negate ? !expr : expr;
+      if (!ok) {
+        throw new AssertionError({
+            message: msg
+          , stackStartFunction: this.assert
+        });
+      }
+    },
+  
+    /**
+     * Dummy getter.
+     *
+     * @api public
+     */
+    
+    get an() {
+      return this;
+    },
+    
+    /**
+     * Dummy getter.
+     *
+     * @api public
+     */
+    
+    get and() {
+      return this;
+    },
+    
+    /**
+     * Dummy getter.
+     *
+     * @api public
+     */
+    
+    get be() {
+      return this;
+    },
+  
+    /**
+     * Dummy getter.
+     *
+     * @api public
+     */
+    
+    get have() {
+      return this;
+    },
+    
+    /**
+     * Dummy getter.
+     *
+     * @api public
+     */
+    
+    get with() {
+      return this;
+    },
+    
+    /**
+     * Inclusion modifier.
+     *
+     * @api public
+     */
+    
+    get include() {
+      this.includes = true;
+      return this;
+    },
+  
+    /**
+     * Negation modifier.
+     *
+     * @api public
+     */
+    
+    get not() {
+      this.negate = true;
+      return this;
+    },
+    
+    /**
+     * Get object inspection string.
+     *
+     * @return {String}
+     * @api private
+     */
+    
+    get inspect() {
+      return i(this.obj);
+    },
+  
+    /**
+     * Assert instanceof `Arguments`.
+     *
+     * @api public
+     */
+  
+    get arguments() {
+      this.assert(
+          '[object Arguments]' == Object.prototype.toString.call(this.obj)
+        , 'expected ' + this.inspect + ' to be arguments'
+        , 'expected ' + this.inspect + ' to not be arguments');
+      return this;
+    },
+  
+    /**
+     * Assert that an object is empty aka length of 0.
+     *
+     * @api public
+     */
+    
+    get empty() {
+      this.obj.should.have.property('length');
+      this.assert(
+          0 === this.obj.length
+        , 'expected ' + this.inspect + ' to be empty'
+        , 'expected ' + this.inspect + ' not to be empty');
+      return this;
+    },
+  
+    /**
+     * Assert ok.
+     *
+     * @api public
+     */
+    
+    get ok() {
+      this.assert(
+          this.obj
+        , 'expected ' + this.inspect + ' to be truthy'
+        , 'expected ' + this.inspect + ' to be falsey');
+      return this;
+    },
+    
+    /**
+     * Assert true.
+     *
+     * @api public
+     */
+    
+    get true() {
+      this.assert(
+          true === this.obj
+        , 'expected ' + this.inspect + ' to be true'
+        , 'expected ' + this.inspect + ' not to be true');
+      return this;
+    },
+    
+    /**
+     * Assert false.
+     *
+     * @api public
+     */
+    
+    get false() {
+      this.assert(
+          false === this.obj
+        , 'expected ' + this.inspect + ' to be false'
+        , 'expected ' + this.inspect + ' not to be false');
+      return this;
+    },
+    
+    /**
+     * Assert equal. 
+     *
+     * @param {Mixed} val
+     * @api public
+     */
+    
+    eql: function(val){
+      this.assert(
+          eql(val, this.obj)
+        , 'expected ' + this.inspect + ' to equal ' + i(val)
+        , 'expected ' + this.inspect + ' to not equal ' + i(val));
+      return this;
+    },
+    
+    /**
+     * Assert strict equal. 
+     *
+     * @param {Mixed} val
+     * @api public
+     */
+    
+    equal: function(val){
+      this.assert(
+          val === this.obj
+        , 'expected ' + this.inspect + ' to equal ' + i(val)
+        , 'expected ' + this.inspect + ' to not equal ' + i(val));
+      return this;
+    },
+    
+    /**
+     * Assert within start to finish (inclusive). 
+     *
+     * @param {Number} start
+     * @param {Number} finish
+     * @api public
+     */
+    
+    within: function(start, finish){
+      var range = start + '..' + finish;
+      this.assert(
+          this.obj >= start && this.obj <= finish
+        , 'expected ' + this.inspect + ' to be within ' + range
+        , 'expected ' + this.inspect + ' to not be within ' + range);
+      return this;
+    },
+    
+    /**
+     * Assert typeof. 
+     *
+     * @api public
+     */
+    
+    a: function(type){
+      this.assert(
+          type == typeof this.obj
+        , 'expected ' + this.inspect + ' to be a ' + type
+        , 'expected ' + this.inspect + ' not to be a ' + type);
+      return this;
+    },
+    
+    /**
+     * Assert instanceof. 
+     *
+     * @api public
+     */
+    
+    instanceof: function(constructor){
+      var name = constructor.name;
+      this.assert(
+          this.obj instanceof constructor
+        , 'expected ' + this.inspect + ' to be an instance of ' + name
+        , 'expected ' + this.inspect + ' not to be an instance of ' + name);
+      return this;
+    },
+  
+    /**
+     * Assert numeric value above _n_.
+     *
+     * @param {Number} n
+     * @api public
+     */
+    
+    above: function(n){
+      this.assert(
+          this.obj > n
+        , 'expected ' + this.inspect + ' to be above ' + n
+        , 'expected ' + this.inspect + ' to be below ' + n);
+      return this;
+    },
+    
+    /**
+     * Assert numeric value below _n_.
+     *
+     * @param {Number} n
+     * @api public
+     */
+    
+    below: function(n){
+      this.assert(
+          this.obj < n
+        , 'expected ' + this.inspect + ' to be below ' + n
+        , 'expected ' + this.inspect + ' to be above ' + n);
+      return this;
+    },
+    
+    /**
+     * Assert string value matches _regexp_.
+     *
+     * @param {RegExp} regexp
+     * @api public
+     */
+    
+    match: function(regexp){
+      this.assert(
+          regexp.exec(this.obj)
+        , 'expected ' + this.inspect + ' to match ' + regexp
+        , 'expected ' + this.inspect + ' not to match ' + regexp);
+      return this;
+    },
+    
+    /**
+     * Assert property "length" exists and has value of _n_.
+     *
+     * @param {Number} n
+     * @api public
+     */
+    
+    length: function(n){
+      this.obj.should.have.property('length');
+      var len = this.obj.length;
+      this.assert(
+          n == len
+        , 'expected ' + this.inspect + ' to have a length of ' + n + ' but got ' + len
+        , 'expected ' + this.inspect + ' to not have a length of ' + len);
+      return this;
+    },
+    
+    /**
+     * Assert substring.
+     *
+     * @param {String} str
+     * @api public
+     */
+  
+    string: function(str){
+      this.obj.should.be.a('string');
+      this.assert(
+          ~this.obj.indexOf(str)
+        , 'expected ' + this.inspect + ' to include ' + i(str)
+        , 'expected ' + this.inspect + ' to not include ' + i(str));
+      return this;
+    },
+  
+    /**
+     * Assert inclusion of object.
+     *
+     * @param {Object} obj
+     * @api public
+     */
+  
+    object: function(obj){
+      this.obj.should.be.a('object');
+      var included = true;
+      for (var key in obj) {
+        if (obj.hasOwnProperty(key) && !eql(obj[key], this.obj[key])) {
+          included = false;
+          break;
+        }
+      }
+      this.assert(
+          included
+        , 'expected ' + this.inspect + ' to include ' + i(obj)
+        , 'expected ' + this.inspect + ' to not include ' + i(obj));
+      return this;
+    },
+  
+    /**
+     * Assert property _name_ exists, with optional _val_.
+     *
+     * @param {String} name
+     * @param {Mixed} val
+     * @api public
+     */
+    
+    property: function(name, val){
+      if (this.negate && undefined !== val) {
+        if (undefined === this.obj[name]) {
+          throw new Error(this.inspect + ' has no property ' + i(name));
+        }
+      } else {
+        this.assert(
+            undefined !== this.obj[name]
+          , 'expected ' + this.inspect + ' to have a property ' + i(name)
+          , 'expected ' + this.inspect + ' to not have a property ' + i(name));
+      }
+      
+      if (undefined !== val) {
+        this.assert(
+            val === this.obj[name]
+          , 'expected ' + this.inspect + ' to have a property ' + i(name)
+            + ' of ' + i(val) + ', but got ' + i(this.obj[name])
+          , 'expected ' + this.inspect + ' to not have a property ' + i(name) + ' of ' + i(val));
+      }
+  
+      this.obj = this.obj[name];
+      return this;
+    },
+    
+    /**
+     * Assert own property _name_ exists.
+     *
+     * @param {String} name
+     * @api public
+     */
+    
+    ownProperty: function(name){
+      this.assert(
+          this.obj.hasOwnProperty(name)
+        , 'expected ' + this.inspect + ' to have own property ' + i(name)
+        , 'expected ' + this.inspect + ' to not have own property ' + i(name));
+      return this;
+    },
+  
+    /**
+     * Assert that the array contains _obj_.
+     *
+     * @param {Mixed} obj
+     * @api public
+     */
+  
+    contain: function(obj){
+      this.obj.should.be.an.instanceof(Array);
+      this.assert(
+          ~this.obj.indexOf(obj)
+        , 'expected ' + this.inspect + ' to contain ' + i(obj)
+        , 'expected ' + this.inspect + ' to not contain ' + i(obj));
+      return this;
+    },
+    
+    /**
+     * Assert exact keys or inclusion of keys by using
+     * the `.include` modifier.
+     *
+     * @param {Array|String ...} keys
+     * @api public
+     */
+    
+    keys: function(keys){
+      var str
+        , ok = true;
+  
+      keys = keys instanceof Array
+        ? keys
+        : Array.prototype.slice.call(arguments);
+  
+      if (!keys.length) throw new Error('keys required');
+  
+      var actual = Object.keys(this.obj)
+        , len = keys.length;
+  
+      // Inclusion
+      ok = keys.every(function(key){
+        return ~actual.indexOf(key);
+      });
+  
+      // Strict
+      if (!this.negate && !this.includes) {
+        ok = ok && keys.length == actual.length;
+      }
+  
+      // Key string
+      if (len > 1) {
+        keys = keys.map(function(key){
+          return i(key);
+        });
+        var last = keys.pop();
+        str = keys.join(', ') + ', and ' + last;
+      } else {
+        str = i(keys[0]);
+      }
+  
+      // Form
+      str = (len > 1 ? 'keys ' : 'key ') + str;
+  
+      // Have / include
+      str = (this.includes ? 'include ' : 'have ') + str;
+  
+      // Assertion
+      this.assert(
+          ok
+        , 'expected ' + this.inspect + ' to ' + str
+        , 'expected ' + this.inspect + ' to not ' + str);
+  
+      return this;
+    },
+  
+    /**
+     * Assert that _method_ is a function.
+     *
+     * @param {String} method
+     * @api public
+     */
+  
+    respondTo: function(method){
+      this.assert(
+        'function' == typeof this.obj[method]
+        , 'expected ' + this.inspect + ' to respond to ' + method + '()'
+        , 'expected ' + this.inspect + ' to not respond to ' + method + '()');
+      return this;
+    },
+    
+    /**
+     * Assert that header `field` has the given `val`. 
+     *
+     * @param {String} field
+     * @param {String} val
+     * @return {Assertion} for chaining
+     * @api public
+     */
+  
+    header: function(field, val){
+      this.obj.should.have.property('headers');
+      this.obj.headers.should.have.property(field.toLowerCase(), val);
+      return this;
+    },
+    
+    /**
+     * Assert `.statusCode` of `code`.
+     *
+     * @param {Number} code
+     * @return {Assertion} for chaining
+     * @api public
+     */
+  
+    status:  function(code){
+      this.obj.should.have.property('statusCode');
+      var status = this.obj.statusCode;
+  
+      this.assert(
+          code == status
+        , 'expected response code of ' + code + ' ' + i(statusCodes[code])
+          + ', but got ' + status + ' ' + i(statusCodes[status])
+        , 'expected to not respond with ' + code + ' ' + i(statusCodes[code]));
+  
+      return this;
+    }
+  };
+  
+  /**
+   * Aliases.
+   */
+  
+  (function alias(name, as){
+    Assertion.prototype[as] = Assertion.prototype[name];
+    return alias;
+  })
+  ('length', 'lengthOf')
+  ('keys', 'key')
+  ('ownProperty', 'haveOwnProperty')
+  ('above', 'greaterThan')
+  ('below', 'lessThan');
+  
+  
+
+ « index | cover.io +
+ + diff --git a/resources/bootstrap.css b/mocha/cover_html/bootstrap.css similarity index 100% rename from resources/bootstrap.css rename to mocha/cover_html/bootstrap.css diff --git a/mocha/cover_html/index.html b/mocha/cover_html/index.html new file mode 100644 index 0000000..b34cc16 --- /dev/null +++ b/mocha/cover_html/index.html @@ -0,0 +1,1156 @@ + + + + + + Coverage Report -- cover.io + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

Coverage Report

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filename % Covered Missed Lines # Lines % Blocks Missed Blocks # Blocks
/Users/itay/Work/mocha/index.js + + + + 100%02100%02
/Users/itay/Work/mocha/lib/browser/progress.js + + + + 78%271263%2526
/Users/itay/Work/mocha/lib/hook.js + + + + 96%13150%24
/Users/itay/Work/mocha/lib/interfaces/bdd.js + + + + 82%158720%1620
/Users/itay/Work/mocha/lib/interfaces/exports.js + + + + 76%146011%1618
/Users/itay/Work/mocha/lib/interfaces/index.js + + + + 100%04100%04
/Users/itay/Work/mocha/lib/interfaces/tdd.js + + + + 82%179510%1820
/Users/itay/Work/mocha/lib/mocha.js + + + + 100%023100%010
/Users/itay/Work/mocha/lib/reporters/base.js + + + + 76%522247%4953
/Users/itay/Work/mocha/lib/reporters/doc.js + + + + 70%22745%3436
/Users/itay/Work/mocha/lib/reporters/dot.js + + + + 70%18626%3032
/Users/itay/Work/mocha/lib/reporters/html.js + + + + 71%441534%7275
/Users/itay/Work/mocha/lib/reporters/index.js + + + + 100%013100%012
/Users/itay/Work/mocha/lib/reporters/json-stream.js + + + + 81%11618%2123
/Users/itay/Work/mocha/lib/reporters/json.js + + + + 77%167010%1719
/Users/itay/Work/mocha/lib/reporters/landing.js + + + + 72%27975%3739
/Users/itay/Work/mocha/lib/reporters/list.js + + + + 70%18616%3032
/Users/itay/Work/mocha/lib/reporters/progress.js + + + + 67%27846%2931
/Users/itay/Work/mocha/lib/reporters/spec.js + + + + 63%30834%4648
/Users/itay/Work/mocha/lib/reporters/tap.js + + + + 78%14648%2325
/Users/itay/Work/mocha/lib/runnable.js + + + + 77%361574%4345
/Users/itay/Work/mocha/lib/runner.js + + + + 72%1144151%156158
/Users/itay/Work/mocha/lib/suite.js + + + + 81%4022115%4553
/Users/itay/Work/mocha/lib/test.js + + + + 90%33350%24
/Users/itay/Work/mocha/lib/utils.js + + + + 84%171105%1920
/Users/itay/Work/mocha/lib/watch.js + + + + 70%51722%79
/Users/itay/Work/mocha/node_modules/commander/index.js + + + + 100%02100%02
/Users/itay/Work/mocha/node_modules/commander/lib/commander.js + + + + 85%13190927%187259
/Users/itay/Work/mocha/node_modules/debug/index.js + + + + 100%02100%02
/Users/itay/Work/mocha/node_modules/debug/lib/debug.js + + + + 92%68553%715
/Users/itay/Work/mocha/node_modules/growl/lib/growl.js + + + + 81%291618%4145
/Users/itay/Work/mocha/node_modules/should/lib/eql.js + + + + 68%29922%3738
/Users/itay/Work/mocha/node_modules/should/lib/should.js + + + + 78%1426463%145150
+
+
+
+ + + +
+ + + diff --git a/resources/jquery.min.js b/mocha/cover_html/jquery.min.js similarity index 100% rename from resources/jquery.min.js rename to mocha/cover_html/jquery.min.js diff --git a/resources/jquery.tablesorter.min.js b/mocha/cover_html/jquery.tablesorter.min.js similarity index 100% rename from resources/jquery.tablesorter.min.js rename to mocha/cover_html/jquery.tablesorter.min.js diff --git a/resources/prettify.css b/mocha/cover_html/prettify.css similarity index 100% rename from resources/prettify.css rename to mocha/cover_html/prettify.css diff --git a/resources/prettify.js b/mocha/cover_html/prettify.js similarity index 100% rename from resources/prettify.js rename to mocha/cover_html/prettify.js diff --git a/package.json b/package.json deleted file mode 100644 index 6176045..0000000 --- a/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name" : "cover", - "version" : "0.2.9", - "description" : "Native JavaScript code coverage", - "main" : "index.js", - "directories" : { - "bin": "bin", - "lib" : ".", - "test" : "test" - }, - "dependencies" : { - "cli-table": "0.0.x", - "underscore": "1.2.x", - "underscore.string": "2.0.x", - "which": "1.0.x" - }, - "repository" : { - "type" : "git", - "url" : "http://github.com/itay/node-cover.git" - }, - "keywords" : [ - "code", - "coverage", - "esprima", - "cover", - "test" - ], - "author" : { - "name" : "Itay Neeman", - "email" : "itay@neeman.net", - "url" : "http://www.pretzelwisdom.com" - }, - "license" : "MIT/X11", - "engine" : { "node" : ">=0.6" }, - "preferGlobal": "true" -} diff --git a/reporters/cli.js b/reporters/cli.js deleted file mode 100644 index b84396f..0000000 --- a/reporters/cli.js +++ /dev/null @@ -1,47 +0,0 @@ -var path = require('path'); -var colors = require('../contrib/colors') - -module.exports.MAX_FILENAME_LENGTH = 60; -module.exports.name = "cli"; -module.exports.format = function(coverageData) { - var stats = coverageData.stats(); - var filename = path.relative(process.cwd(), coverageData.filename); - - if (filename.length > module.exports.MAX_FILENAME_LENGTH) { - filename = "…" + filename.substr(filename.length - module.exports.MAX_FILENAME_LENGTH + 2); - } - - var blockPercentage = Math.floor(stats.blocks.percentage * 100); - var linePercentage = Math.floor(stats.percentage * 100); - - var blockColor = "____"; - if (blockPercentage >= 75) { - blockColor = "green"; - } - else if (blockPercentage >= 50) { - blockColor = "yellow"; - } - else { - blockColor = "red"; - } - - var lineColor = ""; - if (linePercentage >= 75) { - lineColor = "green"; - } - else if (linePercentage >= 50) { - lineColor = "yellow"; - } - else { - lineColor = "red"; - } - - return [ - filename, - (Math.floor(stats.percentage * 100) + "%")[lineColor], - stats.missing, - stats.total, - (Math.floor(stats.blocks.percentage * 100) + "%")[blockColor], - stats.blocks.missing, - stats.blocks.total]; -} \ No newline at end of file diff --git a/reporters/html.js b/reporters/html.js deleted file mode 100644 index 3aa7315..0000000 --- a/reporters/html.js +++ /dev/null @@ -1,83 +0,0 @@ -var fs = require('fs'); -var _ = require('underscore'); - -function htmlEscape(string) { - return string.replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); -} - -module.exports = { - name: "html", - format: function(coverageData) { - var source = coverageData.source.split("\n"); - var stats = coverageData.stats(); - var finalOutput = []; - var fileOutput = []; - - for(var i = 0 ; i < source.length; i++) { - var sourceLine = source[i]; - var line = i; - var lineOutput = []; - if (!stats.coverage.hasOwnProperty(line + 1)) { - lineOutput.push(" "); - lineOutput.push(htmlEscape(sourceLine)); - lineOutput.push(""); - } - else { - var lineInfo = stats.coverage[line + 1]; - sourceLine = lineInfo.source; - - if (!lineInfo.partial) { - // If it isn't partial, then we can just append the entire line - lineOutput.push(" "); - lineOutput.push(htmlEscape(sourceLine)); - lineOutput.push(""); - } - else { - lineOutput.push(" "); - - for(var j = 0; j < lineInfo.missing.length; j++) { - curStart = j == 0 ? 0 : (lineInfo.missing[j-1].endCol + 1); - curEnd = lineInfo.missing[j].startCol; - - lineOutput.push(htmlEscape(sourceLine.slice(curStart, curEnd))); - - lineOutput.push(""); - lineOutput.push(htmlEscape(sourceLine.slice(lineInfo.missing[j].startCol, lineInfo.missing[j].endCol + 1))); - lineOutput.push(""); - } - - // Add the straggling part - curStart = lineInfo.missing[lineInfo.missing.length - 1].endCol + 1; - curEnd = sourceLine.length; - lineOutput.push(htmlEscape(sourceLine.slice(curStart, curEnd))); - - lineOutput.push(""); - } - } - fileOutput.push(lineOutput.join("")); - } - - var lineOutput = []; - for(var i = 0; i < source.length; i++) { - var lineNum = i + 1; - lineOutput.push("

" + lineNum + "

"); - } - - finalOutput.push(""); - finalOutput.push(lineOutput.join("")); - finalOutput.push(""); - finalOutput.push(""); - finalOutput.push("
");
-        finalOutput.push(fileOutput.join("\n"));
-        finalOutput.push("
"); - finalOutput.push(""); - - var outputString = finalOutput.join(""); - - return outputString; - } -} \ No newline at end of file diff --git a/reporters/json.js b/reporters/json.js deleted file mode 100644 index 1ed8131..0000000 --- a/reporters/json.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - name: "json", - format: function(coverageData) { - var source = coverageData.source; - var stats = coverageData.stats(); - var filename = coverageData.filename; - var result = { filename: filename, stats: stats, source: source }; - - return result; - } -} \ No newline at end of file diff --git a/reporters/plain.js b/reporters/plain.js deleted file mode 100644 index 4158317..0000000 --- a/reporters/plain.js +++ /dev/null @@ -1,48 +0,0 @@ -function pad(text, width) { - text = text + ''; - var result = ''; - for (var i = 0; i < width - text.length; i++) { - result += ' '; - } - return result + text; -} - -module.exports = { - name: "plain", - format: function(coverageData) { - var source = coverageData.source.split('\n'); - var stats = coverageData.stats(); - var filename = coverageData.filename; - var result = 'File: ' + filename + '\n\n'; - - for(var i = 0 ; i < source.length; i++) { - var sourceLine = source[i]; - var line = i; - var lineOutput = []; - if (!stats.coverage.hasOwnProperty(line + 1)) { - // ignore covered - } - else { - var lineInfo = stats.coverage[line + 1]; - sourceLine = lineInfo.source; - - if (!lineInfo.partial) { - // If it isn't partial, then we can just append the entire line - result += pad(i + 1, 5) + ' | ' + sourceLine + '\n'; - } - else { - var partialLine = ''; - for(var j = 0; j < lineInfo.missing.length; j++) { - curStart = j == 0 ? 0 : (lineInfo.missing[j-1].endCol + 1); - curEnd = lineInfo.missing[j].startCol; - partialLine += pad('', curEnd - curStart); - partialLine += sourceLine.slice(lineInfo.missing[j].startCol, lineInfo.missing[j].endCol + 1); - } - - result += pad(i + 1, 5) + ' | ' + partialLine + '\n'; - } - } - } - return result + '\n'; - } -} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 10daaae..0000000 --- a/templates/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Coverage Report -- cover.io - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-

Coverage Report

- - - - <% _.each(headers, function(header) { %> <% }); %> - - - - <% _.each(data, function(fileData) { %> - - <% _.each(fileData, function(cell, index) { %> - <% if (index === 0) { %> - - <% } %> - <% }); %> - - <% }); %> - -
<%= header %>
<%= cell %> - <% } else { %> - <%= cell %>
-
-
-
- - - -
- - - diff --git a/templates/instrumentation_header.js b/templates/instrumentation_header.js deleted file mode 100644 index bb8b949..0000000 --- a/templates/instrumentation_header.js +++ /dev/null @@ -1,28 +0,0 @@ - -// Instrumentation Header -{ - var <%= instrumented.names.statement %>, <%= instrumented.names.expression %>, <%= instrumented.names.block %>; - var store = require('<%= coverageStorePath %>'); - var data = store.register('<%= filename %>'); - var nodes = data.nodes; - var blocks = data.blocks; - - <%= instrumented.names.statement %> = function(i) { - var node = nodes[i] = (nodes[i] || {index: i, count:0}) - node.count++; - }; - - <%= instrumented.names.expression %> = function(i) { - var node = nodes[i] = (nodes[i] || {index: i, count:0}) - node.count++; - }; - - <%= instrumented.names.block %> = function(i) { - var block = blocks[i] = (blocks[i] || {index: i, count:0}) - block.count++; - }; -}; -//////////////////////// - -// Instrumented Code -<%= source %> \ No newline at end of file diff --git a/test/format/index.js b/test/format/index.js deleted file mode 100644 index 278da61..0000000 --- a/test/format/index.js +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - -var runforcover = require("../../index"); -var fs = require('fs'); -var path = require('path'); - -var coverage = runforcover.cover(); - -var test1 = require("./src/test1"); -var test2 = require("./src/test2"); - -test1.run(); -test2.run(); - -var types = ['html', 'plain', 'json']; -var outDir = 'test-out'; -try { - fs.statSync(outDir); -} catch (e) { - fs.mkdirSync(outDir, 0755); -} - -coverage(function(coverageData) { - // coverageData is an object keyed by filename. - for(var filename in coverageData) { - if (!coverageData.hasOwnProperty(filename)) { - continue; - } - - types.forEach(function (type) { - - var result = runforcover.formatters[type].format(coverageData[filename]); - var filePath = path.join(outDir, path.basename(filename) + "." + type); - - if (type === 'html') { - result = "" + "\n" - + result; - } - fs.writeFileSync(filePath, result); - }); - - // return control back to the original require function - coverage.release(); - } -}); diff --git a/test/format/src/test1.js b/test/format/src/test1.js deleted file mode 100644 index 9a613a0..0000000 --- a/test/format/src/test1.js +++ /dev/null @@ -1,59 +0,0 @@ -exports.run = function() { - - var abc = function() { - a = 4; - return true; - } - - if (0) { console.log(1); } a = 3; if (0) { console.log(3) } - - if (0) { - console.log(1); - console.log(2); - if (abc()) { console.log(3); console.log(4); } - return; - } - - var printhello = function() { - a = 1; - } - - var printgoodbye = function() { - a + 2; - } - - // Yo yo - printhello(); - - // Hey hey - if (false) { - if (0) { - - console.log(1); - } - - a = function() { - a = 1 + 1 - + 1 + 1 - + 1 + 1; - - b = [ 1, 2, - 3, 4]; - - c = [ - 1, - 2, 3, - 4 - ]; - - if (1 && 2 - && 3 && 4) { - e = 2; - } - } - - if (0) { - console.log(2) - } - } -}; \ No newline at end of file diff --git a/test/format/src/test2.js b/test/format/src/test2.js deleted file mode 100644 index 24cf742..0000000 --- a/test/format/src/test2.js +++ /dev/null @@ -1,8 +0,0 @@ -exports.run = function(a) { - if (a < 0) { - console.log("less!"); - } - else { - console.log("more!"); - } -}; \ No newline at end of file diff --git a/test/index.js b/test/index.js deleted file mode 100644 index ea59662..0000000 --- a/test/index.js +++ /dev/null @@ -1 +0,0 @@ -require('./interface').coverageInterface() diff --git a/test/interface.js b/test/interface.js deleted file mode 100644 index a6455ed..0000000 --- a/test/interface.js +++ /dev/null @@ -1,50 +0,0 @@ -var assert = require('assert'); -var runforcover = require('../'); - -exports.coverageInterface = function() { - assert.ok(runforcover.cover); - - var originalRequire = require.extensions['.js']; - - var coverage = runforcover.cover(); - - assert.notEqual(originalRequire, require.extensions['.js']); - - var file = require('./src/coverage'); - - coverage(function(coverageData) { - assert.equal(Object.keys(coverageData).length, 1); - assert.equal(Object.keys(coverageData)[0], __dirname + '/src/coverage.js'); - - var fileCoverageData = coverageData[Object.keys(coverageData)[0]]; - - assert.ok(fileCoverageData.stats); - assert.ok(fileCoverageData.missing); - - var stats = fileCoverageData.stats(); - - assert.ok(stats.percentage !== undefined); - assert.ok(stats.lines !== undefined); - assert.ok(stats.missing !== undefined); - assert.ok(stats.seen !== undefined); - - assert.equal(stats.lines.length, 3); - assert.equal(stats.lines[0].source(), ' if(a > 0) {'); - assert.equal(stats.lines[1].source(), ' return a + 1;'); - assert.equal(stats.lines[2].source(), ' return a - 1;'); - - file.something(1); - stats = fileCoverageData.stats(); - - assert.equal(stats.lines.length, 1); - assert.equal(stats.lines[0].source(), ' return a - 1;'); - - file.something(-1); - stats = fileCoverageData.stats(); - - assert.equal(stats.lines.length, 0); - - coverage.release(); - assert.equal(require.extensions['.js'], originalRequire); - }); -}; diff --git a/test/src/coverage.js b/test/src/coverage.js deleted file mode 100644 index 4dd9a76..0000000 --- a/test/src/coverage.js +++ /dev/null @@ -1,79 +0,0 @@ -var a = 5 || (c = 5); - -exports.something = function(a) { - if(a > 0) { - b = 1; - c = 2; - d = 3; - } else { - b = 1; - c = function() { - return 5; - }; - d = function() { return 6; - a = 5;}; - f = 11; - if (1) f = 1; if (0) f = 2; - return [a + 1, a + 2, c(), d()]; - return a - 1; - } -}; - -a = function() { - return true; -} - -b = function() { - aa = 5; - return true; -} - -c = function() { - bb = 6; - return false; -} - -if (a() || b() && c()) { - c = 5; -} - -b = function() { - if (a < 0) return; - - a = 1; - b = 2; - c = 3; -} - -b2 = function() { - a2 = 1; - b2 = 2; - c2 = 3; -} - -d = 3; -e = (function() { return 6; })() - -f = d || (g = 3); - -var cond = function() { - return true ? a() : b(); -} - -cond(); - -var g = 1; -g++; - -/*c = 1; -d = function() { - return 1; -} - -e = (function() { - if (1) { - return 2; - } -})(); - -f = 1;*/ \ No newline at end of file diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 7598478..0000000 --- a/test/test.js +++ /dev/null @@ -1,6 +0,0 @@ - -var src = require("./src/coverage") - -src.something(process.argv[2] || 0); - -//console.log(src.something(0)); \ No newline at end of file diff --git a/utils/console.js b/utils/console.js deleted file mode 100644 index 216b43c..0000000 --- a/utils/console.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - A console.log that won't leave you hanging when node exits - 90% of this file was ripped from node.js - - License: see: https://github.com/joyent/node/blob/master/lib/console.js - */ - -var util = require('util'); -var fs = require("fs"); - -/* Monkey patching */ -if (!util.format) { - var formatRegExp = /%[sdj%]/g; - util.format = function(f) { - if (typeof f !== 'string') { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(util.inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': return JSON.stringify(args[i++]); - case '%%': return '%'; - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (x === null || typeof x !== 'object') { - str += ' ' + x; - } else { - str += ' ' + util.inspect(x); - } - } - return str; - } -} - -var consoleFlush = function(data) { - if (!Buffer.isBuffer(data)) { - data= new Buffer(''+ data); - } - if (data.length) { - var written= 0; - do { - try { - var len = data.length- written; - written += fs.writeSync(process.stdout.fd, data, written, len, -1); - } - catch (e) { - } - } while(written < data.length); - } -}; - -var originalConsoleLog = console.log; -var patchedConsoleLog = function() { - var str = util.format.apply(null, arguments) + "\n"; - consoleFlush(str); -}; - -exports.patch = function() { - console.log = patchedConsoleLog; -} - -exports.unpatch = function() { - console.log = originalConsoleLog; -} \ No newline at end of file