Socket
Socket
Sign inDemoInstall

espower

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

espower - npm Package Compare versions

Comparing version 0.8.0 to 0.9.0

CHANGELOG.md

35

gulpfile.js

@@ -7,2 +7,3 @@ var gulp = require('gulp'),

del = require('del'),
path = require('path'),
source = require('vinyl-source-stream'),

@@ -19,2 +20,8 @@ through = require('through2'),

},
source_map_bundle: {
standalone: 'sourceMap',
srcFile: './node_modules/source-map/lib/source-map.js',
destDir: './build',
destName: 'source-map.js'
},
coverage: {

@@ -101,9 +108,5 @@ filename: 'coverage.lcov'

gulp.task('clean_bundle', function (done) {
del([config.bundle.destDir], done);
del([path.join(config.bundle.destDir, config.bundle.destName)], done);
});
gulp.task('clean_coverage', function (done) {
del([config.coverage.filename], done);
});
gulp.task('bundle', ['clean_bundle'], function() {

@@ -117,2 +120,14 @@ var bundleStream = browserify({entries: config.bundle.srcFile, standalone: config.bundle.standalone}).bundle();

gulp.task('clean_source_map_bundle', function (done) {
del([path.join(config.source_map_bundle.destDir, config.source_map_bundle.destName)], done);
});
gulp.task('source_map_bundle', ['clean_source_map_bundle'], function() {
var bundleStream = browserify({entries: config.source_map_bundle.srcFile, standalone: config.source_map_bundle.standalone}).bundle();
return bundleStream
.pipe(source(config.source_map_bundle.destName))
.pipe(derequire())
.pipe(gulp.dest(config.source_map_bundle.destDir));
});
gulp.task('unit', function () {

@@ -122,2 +137,6 @@ return runMochaSimply();

gulp.task('clean_coverage', function (done) {
del([config.coverage.filename], done);
});
gulp.task('coverage', ['clean_coverage'], function () {

@@ -127,3 +146,3 @@ return runMochaWithBlanket();

gulp.task('test_amd', ['bundle'], function () {
gulp.task('test_amd', ['bundle', 'source_map_bundle'], function () {
return gulp

@@ -134,3 +153,3 @@ .src(config.test.amd)

gulp.task('test_browser', ['bundle'], function () {
gulp.task('test_browser', ['bundle', 'source_map_bundle'], function () {
return gulp

@@ -141,4 +160,4 @@ .src(config.test.browser)

gulp.task('clean', ['clean_coverage', 'clean_bundle']);
gulp.task('clean', ['clean_coverage', 'clean_bundle', 'clean_source_map_bundle']);
gulp.task('test', ['unit','test_browser','test_amd']);

@@ -14,3 +14,3 @@ /**

Instrumentor = require('./lib/instrumentor'),
deepCopy = require('./lib/ast-deepcopy'),
clone = require('clone'),
extend = require('xtend');

@@ -29,4 +29,4 @@

espower.deepCopy = deepCopy;
espower.deepCopy = clone;
espower.defaultOptions = defaultOptions;
module.exports = espower;
'use strict';
var estraverse = require('estraverse'),
escodegen = require('escodegen'),
escallmatch = require('escallmatch'),
espurify = require('espurify'),
deepCopy = require('./ast-deepcopy'),
SourceMapConsumer = require('source-map').SourceMapConsumer,
clone = require('clone'),
AssertionVisitor = require('./assertion-visitor'),
typeName = require('type-name'),

@@ -24,18 +24,4 @@ syntax = estraverse.Syntax,

syntax.Property
],
canonicalCodeOptions = {
format: {
indent: {
style: ''
},
newline: ''
},
verbatim: 'x-verbatim-espower'
};
];
// see: https://github.com/Constellation/escodegen/issues/115
if (typeof define === 'function' && define.amd) {
escodegen = window.escodegen;
}
function Instrumentor (options) {

@@ -45,2 +31,5 @@ ensureOptionPrerequisites(options);

this.matchers = options.patterns.map(escallmatch);
if (this.options.sourceMap) {
this.sourceMapConsumer = new SourceMapConsumer(this.options.sourceMap);
}
}

@@ -51,10 +40,5 @@

var that = this,
assertionPath,
argumentPath,
canonicalCode,
powerAssertCallee,
lineNum,
argumentModified = false,
assertionVisitor,
skipping = false,
result = (this.options.destructive) ? ast : deepCopy(ast);
result = (this.options.destructive) ? ast : clone(ast);

@@ -66,59 +50,28 @@ estraverse.replace(result, {

currentPath = path ? path[path.length - 1] : null;
//console.log('enter currentNode:' + currentNode.type + ' parentNode: ' + parentNode.type + ' path: ' + path);
if (argumentPath) {
if ((!isSupportedNodeType(currentNode)) ||
(isLeftHandSideOfAssignment(parentNode, currentPath)) ||
(isObjectLiteralKey(parentNode, currentPath)) ||
(isUpdateExpression(parentNode)) ||
(isCallExpressionWithNonComputedMemberExpression(currentNode, parentNode, currentPath)) ||
(isTypeOfOrDeleteUnaryExpression(currentNode, parentNode, currentPath))) {
skipping = true;
return estraverse.VisitorOption.Skip;
if (assertionVisitor) {
if (assertionVisitor.isCapturingArgument()) {
if (toBeSkipped(currentNode, parentNode, currentPath)) {
skipping = true;
return controller.skip();
}
} else {
return assertionVisitor.enterArgument(currentNode, parentNode, path);
}
} else {
if (!parentNode) {
return undefined;
}
if (that.matchers.some(function (matcher) { return matcher.test(currentNode); })) {
var candidates = that.matchers.filter(function (matcher) { return matcher.test(currentNode); });
if (candidates.length === 1) {
// entering target assertion
lineNum = currentNode.loc.start.line;
canonicalCode = generateCanonicalCode(currentNode);
assertionPath = [].concat(path);
powerAssertCallee = guessPowerAssertCalleeFor(currentNode.callee);
assertionVisitor = new AssertionVisitor(candidates[0], path, that.sourceMapConsumer, that.options);
assertionVisitor.enter(currentNode, parentNode);
return undefined;
}
if (parentNode.type !== syntax.CallExpression || !isSupportedNodeType(currentNode)) {
return undefined;
}
if (parentNode.callee === currentNode) {
// skip callee
return undefined;
}
var argumentMatchResults = that.matchers.map(function (matcher) {
return matcher.matchArgument(currentNode, parentNode);
}).filter(function (result) {
return result !== null;
});
if (argumentMatchResults.length === 1) {
if (argumentMatchResults[0].name === 'message' && argumentMatchResults[0].kind === 'optional') {
// skip optional message argument
return undefined;
}
// entering target argument
argumentPath = [].concat(path);
return undefined;
}
}
return undefined;
},
leave: function (currentNode, parentNode) {
var controller = this,
path = controller.path(),
resultTree = currentNode,
relativeEsPath;
//console.log('leave ' + currentNode.type + ' path: ' + path);
var path = this.path(),
resultTree = currentNode;
if (!assertionVisitor) {
return undefined;
}
if (skipping) {

@@ -128,49 +81,18 @@ skipping = false;

}
if (isPathIdentical(assertionPath, path)) {
// leaving target assertion
canonicalCode = null;
lineNum = null;
assertionPath = null;
powerAssertCallee = null;
if (assertionVisitor.isLeavingAssertion(path)) {
assertionVisitor = null;
return undefined;
}
if (!argumentPath) {
if (!assertionVisitor.isCapturingArgument()) {
return undefined;
}
if (isCalleeOfParent(currentNode, parentNode)) {
return undefined;
}
relativeEsPath = path.slice(assertionPath.length);
//console.log('leave ' + currentNode.type + ' path: ' + path + ' ' + currentNode.name);
switch(currentNode.type) {
case syntax.Identifier:
case syntax.MemberExpression:
case syntax.CallExpression:
case syntax.UnaryExpression:
case syntax.BinaryExpression:
case syntax.LogicalExpression:
case syntax.AssignmentExpression:
case syntax.UpdateExpression:
case syntax.NewExpression:
resultTree = that.captureNode(currentNode, relativeEsPath, powerAssertCallee);
argumentModified = true;
break;
default:
break;
if (toBeCaptured(currentNode)) {
resultTree = assertionVisitor.captureNode(currentNode, path);
}
if (isPathIdentical(argumentPath, path)) {
// leaving target argument
argumentPath = null;
if (argumentModified) {
argumentModified = false;
return that.captureArgument(resultTree, canonicalCode, powerAssertCallee, lineNum);
}
if (assertionVisitor.isLeavingArgument(path)) {
return assertionVisitor.leaveArgument(resultTree);
}
return resultTree;

@@ -182,114 +104,33 @@ }

Instrumentor.prototype.captureArgument = function (node, canonicalCode, powerAssertCallee, lineNum) {
var n = newNodeWithLocationCopyOf(node),
props = [],
newCallee = updateLocRecursively(espurify(powerAssertCallee), n);
addLiteralTo(props, n, 'content', canonicalCode);
addLiteralTo(props, n, 'filepath', this.options.path);
addLiteralTo(props, n, 'line', lineNum);
return n({
type: syntax.CallExpression,
callee: n({
type: syntax.MemberExpression,
computed: false,
object: newCallee,
property: n({
type: syntax.Identifier,
name: '_expr'
})
}),
arguments: [node].concat(n({
type: syntax.ObjectExpression,
properties: props
}))
});
};
Instrumentor.prototype.captureNode = function (target, relativeEsPath, powerAssertCallee) {
var n = newNodeWithLocationCopyOf(target),
newCallee = updateLocRecursively(espurify(powerAssertCallee), n);
return n({
type: syntax.CallExpression,
callee: n({
type: syntax.MemberExpression,
computed: false,
object: newCallee,
property: n({
type: syntax.Identifier,
name: '_capt'
})
}),
arguments: [
target,
n({
type: syntax.Literal,
value: relativeEsPath.join('/')
})
]
});
};
function updateLocRecursively (node, n) {
estraverse.replace(node, {
leave: function (currentNode, parentNode) {
return n(currentNode);
}
});
return node;
function isCalleeOfParent(currentNode, parentNode) {
return (parentNode.type === syntax.CallExpression || parentNode.type === syntax.NewExpression) &&
parentNode.callee === currentNode;
}
function guessPowerAssertCalleeFor (node) {
switch(node.type) {
function toBeCaptured (currentNode) {
switch(currentNode.type) {
case syntax.Identifier:
return node;
case syntax.MemberExpression:
return node.object; // Returns browser.assert when browser.assert.element(selector)
case syntax.CallExpression:
case syntax.UnaryExpression:
case syntax.BinaryExpression:
case syntax.LogicalExpression:
case syntax.AssignmentExpression:
case syntax.UpdateExpression:
case syntax.NewExpression:
return true;
default:
return false;
}
return null;
}
function generateCanonicalCode(node) {
var ast = deepCopy(node);
estraverse.replace(ast, {
leave: function (currentNode, parentNode) {
if (currentNode.type === syntax.Literal && typeof currentNode.raw !== 'undefined') {
currentNode['x-verbatim-espower'] = {
content : currentNode.raw,
precedence : escodegen.Precedence.Primary
};
return currentNode;
} else {
return undefined;
}
}
});
return escodegen.generate(ast, canonicalCodeOptions);
function toBeSkipped (currentNode, parentNode, currentPath) {
return !isSupportedNodeType(currentNode) ||
isLeftHandSideOfAssignment(parentNode, currentPath) ||
isObjectLiteralKey(parentNode, currentPath) ||
isUpdateExpression(parentNode) ||
isCallExpressionWithNonComputedMemberExpression(currentNode, parentNode, currentPath) ||
isTypeOfOrDeleteUnaryExpression(currentNode, parentNode, currentPath);
}
function addLiteralTo(props, createNode, name, data) {
if (data) {
addToProps(props, createNode, name, createNode({
type: syntax.Literal,
value: data
}));
}
}
function addToProps(props, createNode, name, value) {
props.push(createNode({
type: syntax.Property,
key: createNode({
type: syntax.Identifier,
name: name
}),
value: value,
kind: 'init'
}));
}
function isCalleeOfParent(currentNode, parentNode) {
return (parentNode.type === syntax.CallExpression || parentNode.type === syntax.NewExpression) &&
parentNode.callee === currentNode;
}
function isLeftHandSideOfAssignment(parentNode, currentPath) {

@@ -320,21 +161,2 @@ // Do not instrument left due to 'Invalid left-hand side in assignment'

function isPathIdentical(path1, path2) {
if (!path1 || !path2) {
return false;
}
return path1.join('/') === path2.join('/');
}
function newNodeWithLocationCopyOf (original) {
return function (newNode) {
if (typeof original.loc !== 'undefined') {
newNode.loc = deepCopy(original.loc);
}
if (typeof original.range !== 'undefined') {
newNode.range = deepCopy(original.range);
}
return newNode;
};
}
function isSupportedNodeType (node) {

@@ -341,0 +163,0 @@ return supportedNodeTypes.indexOf(node.type) !== -1;

{
"name": "espower",
"description": "Power Assert feature instrumentor based on the Mozilla JavaScript AST",
"version": "0.8.0",
"keywords": [
"power-assert",
"test",
"assert",
"testing",
"ecmascript",
"ast"
],
"homepage": "http://github.com/twada/espower",
"version": "0.9.0",
"author": {

@@ -19,29 +10,12 @@ "name": "Takuto Wada",

},
"main": "./index.js",
"files": [
"gulpfile.js",
"MIT-LICENSE.txt",
"README.md",
"index.js",
"lib",
"package.json",
"test"
],
"directories": {
"lib": "./lib"
"bugs": {
"url": "http://github.com/twada/espower/issues"
},
"repository": {
"type": "git",
"url": "http://github.com/twada/espower.git"
},
"scripts": {
"bower": "bower install --config.interactive=false",
"test": "gulp test",
"coveralls": "gulp coverage && cat ./coverage.lcov | coveralls"
},
"dependencies": {
"escallmatch": "~0.3.0",
"clone": "~0.1.18",
"escallmatch": "~0.3.1",
"escodegen": "~1.3.3",
"espurify": "~0.1.3",
"estraverse": "~1.5.1",
"source-map": "~0.1.38",
"type-name": "~1.0.0",

@@ -52,8 +26,8 @@ "xtend": "~4.0.0"

"blanket": "~1.1.6",
"browserify": "~5.9.1",
"del": "~0.1.1",
"browserify": "~5.10.0",
"del": "~0.1.2",
"esprima": "~1.2.2",
"gulp": "~3.8.7",
"gulp-derequire": "~0.3.0",
"gulp-mocha": "~0.5.2",
"gulp-derequire": "~0.3.1",
"gulp-mocha": "~1.0.0",
"gulp-mocha-phantomjs": "~0.3.0",

@@ -67,11 +41,38 @@ "gulp-util": "~3.0.0",

},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/twada/espower/blob/master/MIT-LICENSE.txt"
}
"directories": {
"lib": "./lib"
},
"files": [
"CHANGELOG.md",
"MIT-LICENSE.txt",
"README.md",
"gulpfile.js",
"index.js",
"lib",
"package.json",
"test"
],
"bugs": {
"url": "http://github.com/twada/espower/issues"
"homepage": "http://github.com/twada/espower",
"keywords": [
"power-assert",
"test",
"assert",
"testing",
"ecmascript",
"ast"
],
"license": {
"type": "MIT",
"url": "https://github.com/twada/espower/blob/master/MIT-LICENSE.txt"
},
"main": "./index.js",
"repository": {
"type": "git",
"url": "http://github.com/twada/espower.git"
},
"scripts": {
"bower": "bower install --config.interactive=false",
"test": "gulp test",
"coveralls": "gulp coverage && cat ./coverage.lcov | coveralls"
}
}

@@ -8,2 +8,3 @@ espower

[![Coverage Status](https://coveralls.io/repos/twada/espower/badge.png?branch=master)](https://coveralls.io/r/twada/espower?branch=master)
[![Code Climate](https://codeclimate.com/github/twada/espower/badges/gpa.svg)](https://codeclimate.com/github/twada/espower)
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/twada/espower/blob/master/MIT-LICENSE.txt)

@@ -108,2 +109,11 @@ [![Built with Gulp](http://img.shields.io/badge/built_with-gulp-brightgreen.svg)](http://gulpjs.com/)

#### (optional) options.sourceMap
| type | default value |
|:--------------------|:--------------|
| `object` or `string`| N/A |
A raw (either as a string which can be JSON.parse'd, or an object) [SourceMap](https://github.com/mozilla/source-map/) associated with `originalAst`. This property is optional. If given, espower uses `options.sourceMap` to adjust information in the power-assert output.
### var options = espower.defaultOptions();

@@ -110,0 +120,0 @@

(function (root, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['espower', 'esprima', 'escodegen', 'estraverse', 'assert'], factory);
define(['espower', 'esprima', 'escodegen', 'estraverse', 'source-map', 'assert'], factory);
} else if (typeof exports === 'object') {
factory(require('..'), require('esprima'), require('escodegen'), require('estraverse'), require('assert'));
factory(require('..'), require('esprima'), require('escodegen'), require('estraverse'), require('source-map'), require('assert'));
} else {
factory(root.espower, root.esprima, root.escodegen, root.estraverse, root.assert);
factory(root.espower, root.esprima, root.escodegen, root.estraverse, root.sourceMap, root.assert);
}

@@ -15,8 +15,12 @@ }(this, function (

estraverse,
sourceMap,
assert
) {
// see: https://github.com/Constellation/escodegen/issues/115
if (typeof define === 'function' && define.amd) {
// see: https://github.com/Constellation/escodegen/issues/115
escodegen = window.escodegen;
// TypeError: 'undefined' is not an object (evaluating 'global.sourceMap.SourceNode')
// at generate (bower_components/escodegen/escodegen.browser.js:1845)
window.sourceMap = sourceMap;
}

@@ -40,2 +44,14 @@

});
it('patterns: Array', function () {
assert.deepEqual(this.options.patterns, [
'assert(value, [message])',
'assert.ok(value, [message])',
'assert.equal(actual, expected, [message])',
'assert.notEqual(actual, expected, [message])',
'assert.strictEqual(actual, expected, [message])',
'assert.notStrictEqual(actual, expected, [message])',
'assert.deepEqual(actual, expected, [message])',
'assert.notDeepEqual(actual, expected, [message])'
]);
});
});

@@ -220,2 +236,69 @@

describe('SourceMap support', function () {
it('adjust line number', function () {
var originalPath = '/path/to/absolute/original_test.js';
var originalCode = 'var str = "foo";\nvar anotherStr = "bar"\n\nassert.equal(\nstr,\nanotherStr\n);';
// console.log(originalCode);
var compactResult = escodegen.generate(esprima.parse(originalCode, {tolerant: true, loc: true, source: originalPath}), {
format: {
compact: true
},
sourceMap: true,
sourceMapWithCode: true
});
var compactCode = compactResult.code;
// console.log(compactCode);
var sourceMap = compactResult.map.toString();
// console.log(sourceMap);
var espoweredAST = espower(esprima.parse(compactCode, {tolerant: true, loc: true, source: originalPath}), {
patterns: [
'assert.equal(actual, expected, [message])'
],
sourceMap: sourceMap
});
var espoweredCode = escodegen.generate(espoweredAST, {format: {compact: true}});
assert.equal(espoweredCode, "var str='foo';var anotherStr='bar';assert.equal(assert._expr(assert._capt(str,'arguments/0'),{content:'assert.equal(str, anotherStr)',filepath:'/path/to/absolute/original_test.js',line:4}),assert._expr(assert._capt(anotherStr,'arguments/1'),{content:'assert.equal(str, anotherStr)',filepath:'/path/to/absolute/original_test.js',line:4}));");
});
it('when sourceRoot is given', function () {
var originalBasePath = '/path/to/base/';
var originalRelativePath = 'original_test.js';
var originalCode = 'var str = "foo";\nvar anotherStr = "bar"\n\nassert.equal(\nstr,\nanotherStr\n);';
// console.log(originalCode);
var compactResult = escodegen.generate(esprima.parse(originalCode, {tolerant: true, loc: true, source: originalBasePath + originalRelativePath}), {
format: {
compact: true
},
sourceMap: true,
sourceMapRoot: originalBasePath,
sourceMapWithCode: true
});
var compactCode = compactResult.code;
// console.log(compactCode);
var sourceMap = compactResult.map.toString();
// console.log(sourceMap);
var espoweredAST = espower(esprima.parse(compactCode, {tolerant: true, loc: true, source: originalBasePath + originalRelativePath}), {
patterns: [
'assert.equal(actual, expected, [message])'
],
sourceMap: sourceMap
});
var espoweredCode = escodegen.generate(espoweredAST, {format: {compact: true}});
assert.equal(espoweredCode, "var str='foo';var anotherStr='bar';assert.equal(assert._expr(assert._capt(str,'arguments/0'),{content:'assert.equal(str, anotherStr)',filepath:'/path/to/base/original_test.js',line:4}),assert._expr(assert._capt(anotherStr,'arguments/1'),{content:'assert.equal(str, anotherStr)',filepath:'/path/to/base/original_test.js',line:4}));");
});
});
}));

@@ -76,6 +76,8 @@ (function (root, factory) {

"assert(false,messageStr);");
inst("assert.equal(foo, 'bar', 'msg');",
"assert.equal(assert._expr(assert._capt(foo,'arguments/0'),{content:'assert.equal(foo, \\'bar\\', \\'msg\\')',filepath:'/path/to/some_test.js',line:1}),'bar','msg');");
});
describe('multiline, multiassert', function () {

@@ -82,0 +84,0 @@ inst("assert.equal(\nstr,\nanotherStr\n);\n\nassert.equal(\nstr,\nyetAnotherStr\n);",

@@ -8,2 +8,3 @@ var require = {

estraverse: '../bower_components/estraverse/estraverse',
"source-map": '../build/source-map',
mocha: '../bower_components/mocha/mocha',

@@ -10,0 +11,0 @@ requirejs: '../bower_components/requirejs/require'

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc