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

jsstana

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsstana - npm Package Compare versions

Comparing version 0.0.11 to 0.0.12

CHANGELOG.md

8

Gruntfile.js

@@ -16,9 +16,2 @@ "use strict";

},
mochacov: {
options: {
reporter: "html-cov",
output: "coverage.html",
},
all: { src: "test/**/*.js" }
},
jshint: {

@@ -64,3 +57,2 @@ options: {

grunt.loadNpmTasks("grunt-simple-mocha");
grunt.loadNpmTasks("grunt-mocha-cov");
grunt.loadNpmTasks("grunt-literate");

@@ -67,0 +59,0 @@

877

lib/jsstana.js
/**
# jsstana [![Build Status](https://secure.travis-ci.org/phadej/jsstana.png?branch=master)](http://travis-ci.org/phadej/jsstana)
# jsstana
s-expression match patterns for [Mozilla Parser AST](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)
> s-expression match patterns for [Mozilla Parser AST](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)
[![Build Status](https://secure.travis-ci.org/phadej/jsstana.png?branch=master)](http://travis-ci.org/phadej/jsstana)
[![NPM version](https://badge.fury.io/js/jsstana.png)](http://badge.fury.io/js/jsstana)
[![Dependency Status](https://gemnasium.com/phadej/jsstana.png)](https://gemnasium.com/phadej/jsstana)
[![Code Climate](https://codeclimate.com/github/phadej/jsstana.png)](https://codeclimate.com/github/phadej/jsstana)
## Synopsis

@@ -29,11 +34,13 @@

# find assertArguments calls with 4 arguments
% jsgrep '(call assertArguments ? ? ? ?)' lib
jsstana.js:224: assertArguments("true/false/null/infinity/nan/undefined", 0, arguments, 1);
jsstana.js:255: assertArguments("literal", 1, arguments, 1);
jsstana.js:485: assertArguments("member/property/subscript", 2, arguments, 1);
% jsgrep '(call ?.assertArguments ? ? ? ?)' lib
matchers/literal.js:25: this.assertArguments("true/false/null/infinity/nan/undefined", 0, arguments, 1);
matchers/literal.js:111: this.assertArguments("literal", 1, arguments, 1);
matchers/member.js:18: that.assertArguments("member/property/subscript", 2, arguments, 1);
matchers/operator.js:63: that.assertArguments(ratorName, 3, arguments, 3);
matchers/operator.js:98: that.assertArguments("unary", 2, arguments, 1);
matchers/operator.js:128: that.assertArguments("update/postfix/prefix", 2, arguments, 1);
matchers/simple.js:7: this.assertArguments(rator, 1, arguments, 3);
```
*/
## Documentation
*/
"use strict";

@@ -44,2 +51,3 @@

var sexpr = require("./sexpr.js");
var levenshtein = require("levenshtein");

@@ -69,10 +77,45 @@ // Generic traversing function

// pattern maker
var builtInMatchers = {};
_.extend(builtInMatchers, require("./matchers/logic.js"));
_.extend(builtInMatchers, require("./matchers/literal.js"));
_.extend(builtInMatchers, require("./matchers/operator.js"));
_.extend(builtInMatchers, require("./matchers/simple.js"));
_.extend(builtInMatchers, require("./matchers/call.js"));
_.extend(builtInMatchers, require("./matchers/ident.js"));
_.extend(builtInMatchers, require("./matchers/member.js"));
_.extend(builtInMatchers, require("./matchers/null.js"));
_.extend(builtInMatchers, require("./matchers/ternary.js"));
function identifierMatcher(sexpr) {
assert(_.isString(sexpr), "identifier expression should be a string");
function unknownNodeType(rator) {
/* jshint validthis:true */
var suggest = [];
function findClose(key) {
var d = new levenshtein(rator, key).distance;
if (sexpr === "?") {
return function (node) {
assert(node.type === "Identifier", "identifier matcher expects identifier nodes");
if (d <= 2) {
suggest.push(key);
}
}
_.chain(this.matchers).keys().each(findClose);
_.chain(builtInMatchers).keys().each(findClose);
if (suggest.length === 0) {
throw new Error("unknown node type: " + rator);
} else {
throw new Error("unknown node type: " + rator + ". Did you mean one of: " + suggest.join(" "));
}
}
function matcherString(sexpr) {
/* jshint validthis:true */
var that = this;
if (sexpr.indexOf(".") !== -1) {
sexpr = sexpr.split(".").reduce(function (prev, next) {
return ["property", prev, next];
});
return that.matcher(sexpr);
} else if (sexpr === "?") {
return function () {
return {};

@@ -83,29 +126,26 @@ };

return function (node) {
assert(node.type === "Identifier", "identifier matcher expects identifier nodes");
var res = {};
res[sexpr] = node.name;
res[sexpr] = node;
return res;
};
} else {
} else if (sexpr.match(/^\$\d+$/)) {
sexpr = parseInt(sexpr.substr(1), 10);
assert(sexpr < that.positionalMatchers.length,
"there is only " + that.positionalMatchers.length + " positional matchers, required " + sexpr);
return that.positionalMatchers[sexpr];
} else if (sexpr === "true") {
return function (node) {
assert(node.type === "Identifier", "identifier matcher expects identifier nodes");
return node.name === sexpr ? {} : undefined;
return node.type === "Literal" && node.value === true ? {} : undefined;
};
}
}
function operatorMatcher(operator, validOperators) {
if (operator === "?") {
return function () { return {}; };
} else if (operator[0] === "?") {
operator = operator.substr(1);
return function(op) {
var res = {};
res[operator] = op;
return res;
} else if (sexpr === "false") {
return function (node) {
return node.type === "Literal" && node.value === false ? {} : undefined;
};
} else if (sexpr === "null") {
return function (node) {
return node.type === "Literal" && node.value === null ? {} : undefined;
};
} else {
assert(_.contains(validOperators, operator), operator + " is not valid operator");
return function (op) {
return op === operator ? {} : undefined;
return function (node) {
return node.type === "Identifier" && node.name === sexpr ? {} : undefined;
};

@@ -115,81 +155,29 @@ }

// http://ecma-international.org/ecma-262/5.1/#sec-7.7
var validBinaryOperators = [
"+", "-", "*", "/", "%",
"<<", ">>", ">>>",
"<", ">", "<=", ">=",
"==", "!=", "===", "!==",
"&&", "||",
"&", "|", "^",
];
function matcherNumber(sexpr) {
return function (node) {
return node.type === "Literal" && node.value === sexpr ? {} : undefined;
};
}
var validUnaryOperators = [
"!", "~", "+", "-",
];
function matcherArray(sexpr) {
/* jshint validthis:true */
var that = this;
var rator = _.first(sexpr);
var rands = _.rest(sexpr);
var validUpdateOperators = [
"++", "--",
];
if (_.has(that.matchers, rator)) {
return that.matchers[rator].apply(that, rands);
} else if (_.has(builtInMatchers, rator)) {
return builtInMatchers[rator].apply(that, rands);
} else {
return unknownNodeType.call(that, rator);
}
}
var validAssignmentOperators = [
"=",
"+=", "-=", "*=", "/=", "%=",
"<<=", ">>=", ">>>=",
"&=", "|=", "^=",
];
function matcher(sexpr) {
/* jshint validthis:true */
var builtInMatchers = {
"not": notMatcher,
"or": orMatcher,
"and": andMatcher,
"var": varMatcher,
"ident": identMatcher,
"return": returnMatcher,
"call": _.partial(callMatcher, true),
"new": _.partial(callMatcher, false),
"expr": expressionMatcher,
"binary": binaryMatcher,
"unary": unaryMatcher,
"update": _.partial(updateMatcher, undefined),
"prefix": _.partial(updateMatcher, true),
"postfix": _.partial(updateMatcher, false),
"assign": assignMatcher,
"member": _.partial(memberMatcher, undefined),
"property": _.partial(memberMatcher, false),
"subscript": _.partial(memberMatcher, true),
"lookup": lookupMatcher,
"throw": throwMatcher,
"ternary": ternaryMatcher,
"literal": _.partial(literalMatcher, "any"),
"string": _.partial(literalMatcher, "string"),
"number": _.partial(literalMatcher, "number"),
"bool": _.partial(literalMatcher, "bool"),
"regexp": _.partial(literalMatcher, "regexp"),
"null": _.partial(literalBuiltinMatcher, "null"),
"true": _.partial(literalBuiltinMatcher, "true"),
"false": _.partial(literalBuiltinMatcher, "false"),
"infinity": _.partial(literalBuiltinMatcher, "infinity"),
"nan": _.partial(literalBuiltinMatcher, "nan"),
"undefined": _.partial(literalBuiltinMatcher, "undefined"),
"null-node": nullNodeMatcher,
};
assert(_.isString(sexpr) || _.isNumber(sexpr) || _.isArray(sexpr),
"expression should be a number, a string or an array -- " + sexpr);
var unaryOperators = _.difference(validUnaryOperators, validBinaryOperators);
// "TODO: , == SequenceExpression"
_.each(validBinaryOperators, function (binop) {
builtInMatchers[binop] = _.partial(binaryMatcher, binop);
});
_.each(unaryOperators, function (unop) {
builtInMatchers[unop] = _.partial(unaryMatcher, unop);
});
_.each(validAssignmentOperators, function (assignOp) {
builtInMatchers[assignOp] = _.partial(assignMatcher, assignOp);
});
function matcher(sexpr) {
/* jshint validthis:true */
var that = this instanceof JsstanaContext ? this : new JsstanaContext();

@@ -203,60 +191,8 @@ var args = _.toArray(arguments).slice(1);

if (_.isString(sexpr)) {
if (sexpr.indexOf(".") !== -1) {
sexpr = sexpr.split(".").reduce(function (prev, next) {
return ["property", prev, next];
});
return that.matcher(sexpr);
} else if (sexpr === "?") {
return function () {
return {};
};
} else if (sexpr[0] === "?") {
sexpr = sexpr.substr(1);
return function (node) {
var res = {};
res[sexpr] = node;
return res;
};
} else if (sexpr.match(/^\$\d+$/)) {
sexpr = parseInt(sexpr.substr(1), 10);
assert(sexpr < that.positionalMatchers.length,
"there is only " + that.positionalMatchers.length + " positional matchers, required " + sexpr);
return that.positionalMatchers[sexpr];
} else if (sexpr === "true") {
return function (node) {
return node.type === "Literal" && node.value === true ? {} : undefined;
};
} else if (sexpr === "false") {
return function (node) {
return node.type === "Literal" && node.value === false ? {} : undefined;
};
} else if (sexpr === "null") {
return function (node) {
return node.type === "Literal" && node.value === null ? {} : undefined;
};
} else {
return function (node) {
return node.type === "Identifier" && node.name === sexpr ? {} : undefined;
};
}
return matcherString.call(that, sexpr);
} else if (_.isNumber(sexpr)) {
return matcherNumber.call(that, sexpr);
} else /* if (_.isArray(sexpr)) */ {
return matcherArray.call(that, sexpr);
}
if (_.isNumber(sexpr)) {
return function (node) {
return node.type === "Literal" && node.value === sexpr ? {} : undefined;
};
}
assert(_.isArray(sexpr), "expression should be a number, a string or an array -- " + sexpr);
var rator = _.first(sexpr);
var rands = _.rest(sexpr);
if (_.has(that.matchers, rator)) {
return that.matchers[rator].apply(that, rands);
} else if (_.has(builtInMatchers, rator)) {
return builtInMatchers[rator].apply(that, rands);
} else {
throw new Error("unknown node type: " + rator);
}
}

@@ -276,559 +212,19 @@

/**
### Pattern syntax
## Pattern syntax
*/
/**
#### (not pattern)
/// include matchers/logic.js
/// include matchers/call.js
/// include matchers/ident.js
/// include matchers/null.js
/// include matchers/literal.js
/// include matchers/simple.js
/// include matchers/member.js
/// include matchers/operator.js
/// include matchers/ternary.js
Matches when `pattern` doesn't match.
*/
function notMatcher(pattern) {
/* jshint validthis:true */
assertArguments("not", 1, arguments);
pattern = pattern || "?";
var patternMatcher = this.matcher(pattern);
return function (node) {
return patternMatcher(node) ? undefined : {};
};
}
/**
#### (or pattern1 pattern2...)
Matches if any pattern matches, returns first match.
## API
*/
function orMatcher() {
/* jshint validthis:true */
var args = _.toArray(arguments);
var argsMatchers = args.map(matcher, this);
return function (node) {
for (var i = 0; i < argsMatchers.length; i++) {
var m = argsMatchers[i](node);
if (m) {
return m;
}
}
return undefined;
};
}
/**
#### (and pattern1 pattern2...)
Matches if all pattern matches, returns combinedMatch
*/
function andMatcher() {
/* jshint validthis:true */
var args = _.toArray(arguments);
var argsMatchers = args.map(matcher, this);
return function (node) {
var res = {};
for (var i = 0; i < argsMatchers.length; i++) {
var m = argsMatchers[i](node);
if (m === undefined) {
return undefined;
}
res = _.extend(res, m);
}
return res;
};
}
/**
#### (null-node)
Matches `undefined` node.
*/
function nullNodeMatcher() {
assertArguments("null-node", 0, arguments);
return function (node) {
return node === null ? {} : undefined;
};
}
/**
#### (return value)
Matches `ReturnStatement`.
*/
function returnMatcher(value) {
/* jshint validthis:true */
assertArguments("return", 1, arguments);
value = value || "?";
var valueMatcher = this.matcher(value);
return function (node) {
if (node.type !== "ReturnStatement") { return undefined; }
return valueMatcher(node.argument);
};
}
/**
#### (literal value)
Matches `Literal`.
There are some additional version:
- `(string value)` - string values
- `(number value)` - number values
- `(bool value)` - boolean values
- `(regexp value)` - regular expressions
- `(true)` - matches `true`
- `(false)` - matches `false`
- `(null)` - matches `null`
- `(infinity)` - matches `Infinity`
- `(nan)` - matches `NaN`
- `(undefined)` - matches `undefined`
*/
function literalBuiltinMatcher(type) {
assertArguments("true/false/null/infinity/nan/undefined", 0, arguments, 1);
// Constants
if (type === "true") {
return function (node) {
return node.type === "Literal" && node.value === true ? {} : undefined;
};
} else if (type === "false") {
return function (node) {
return node.type === "Literal" && node.value === false ? {} : undefined;
};
} else if (type === "null") {
return function (node) {
return node.type === "Literal" && node.value === null ? {} : undefined;
};
} else if (type === "infinity") {
return function (node) {
return node.type === "Identifier" && node.name === "Infinity" ? {} : undefined;
};
} else if (type === "nan") {
return function (node) {
return node.type === "Identifier" && node.name === "NaN" ? {} : undefined;
};
} else /* if (type === "undefined") */ {
return function (node) {
return node.type === "Identifier" && node.name === "undefined" ? {} : undefined;
};
}
}
function literalMatcher(type, value) {
assertArguments("literal", 1, arguments, 1);
value = value || "?";
if (value[0] === "?") {
var valueCheck = {
any: function () { return true; },
string: _.isString,
number: _.isNumber,
regexp: _.isRegExp,
bool: _.isBoolean,
}[type];
var valueCapture;
if (value === "?") {
valueCapture = function() { return {}; };
} else {
value = value.substr(1);
valueCapture = function(v) {
var res = {};
res[value] = v;
return res;
};
}
return function (node) {
if (node.type !== "Literal") { return undefined; }
if (!valueCheck(node.value)) { return undefined; }
return valueCapture(node.value);
};
} else {
if (type === "regexp") {
return function (node) {
if (node.type !== "Literal") { return undefined; }
if (!_.isRegExp(node.value)) { return undefined; }
return node.value.toString() === value ? {} : undefined;
};
} else {
value = {
any: _.identity,
string: _.identity,
number: function (v) {
v = parseFloat(v);
if (isNaN(v)) {
// TODO: improve check, regexp?
throw new Error("invalid number value");
} else {
return v;
}
},
bool: function (v) {
if (v === "true") {
return true;
} else if (v === "false") {
return false;
} else {
throw new Error("bool values are true and false");
}
}
}[type](value);
return function (node) {
if (node.type !== "Literal") { return undefined; }
return node.value === value ? {} : undefined;
};
}
}
}
/**
#### (var name init)
Matches `VariableDeclarator`.
*/
function varMatcher(id, init) {
/* jshint validthis:true */
assertArguments("var", 2, arguments);
id = id || "?";
init = init || "?";
var idMatcher = identifierMatcher(id);
var initMatcher = this.matcher(init);
return function (node) {
if (node.type !== "VariableDeclarator") { return undefined; }
var idM = idMatcher(node.id);
var initM = initMatcher(node.init);
return combineMatches(idM, initM);
};
}
/**
#### (ident name)
Matches `Identifier`.
*/
function identMatcher(name) {
assertArguments("ident", 1, arguments);
name = name || "?";
var nameMatcher = identifierMatcher(name);
return function (node) {
if (node.type !== "Identifier") { return undefined; }
return nameMatcher(node);
};
}
/**
#### (call callee arg0...argn)
Matches `CallExpression`.
`(call fun arg1 arg2)` matches exact amount of arguments,
for arbitrary arguments use
`(call fun . ?)` or similar dotted list syntax.
*/
function callMatcher(callnew, callee) {
/* jshint validthis:true */
callee = callee || "?";
var calleeMatcher = this.matcher(callee);
var args = _.toArray(arguments).slice(2);
var dotted = false;
var dottedM;
if (args.length > 1 && args[args.length - 2] === ".") {
dotted = args[args.length - 1];
args = args.slice(0, -2);
if (dotted === "?") {
dottedM = function () {
return {};
};
} else if (dotted[0] === "?") {
dotted = dotted.substr(1);
dottedM = function(v) {
var res = {};
res[dotted] = v;
return res;
};
} else {
throw new Error("call should have pattern variable after dot");
}
}
var argumentMatchers = args.map(matcher, this);
return function (node) {
if (node.type !== (callnew ? "CallExpression" : "NewExpression")) { return undefined; }
var calleeM = calleeMatcher(node.callee);
if (calleeM === undefined) { return undefined; }
if (!dotted && argumentMatchers.length !== node.arguments.length) { return undefined; }
for (var i = 0; i < argumentMatchers.length; i++) {
var argumentM = argumentMatchers[i](node.arguments[i]);
if (argumentM === undefined) { return undefined; }
calleeM = _.extend(calleeM, argumentM);
}
if (dottedM) {
calleeM = _.extend(calleeM, dottedM(node.arguments.slice(argumentMatchers.length)));
}
return calleeM;
};
}
/**
#### (expression expr)
Matches expression statement, `ExpressionStatement`.
*/
function expressionMatcher(expr) {
/* jshint validthis:true */
assertArguments("expr", 1, arguments);
expr = expr || "?";
var exprMatcher = this.matcher(expr);
return function (node) {
if (node.type !== "ExpressionStatement") { return undefined; }
return exprMatcher(node.expression);
};
}
/**
#### (binary op lhs rhs)
Matches `BinaryExpression`.
Also shorthand syntax is supported, `(+ a b)` is the same as `(binary + a b)`.
*/
function binaryMatcher(operator, lhs, rhs) {
/* jshint validthis:true */
assertArguments("binary", 3, arguments);
operator = operator || "?";
lhs = lhs || "?";
rhs = rhs || "?";
assert(_.isString(operator), "binary operator should be string expr");
var opMatcher = operatorMatcher(operator, validBinaryOperators);
var lhsMatcher = this.matcher(lhs);
var rhsMatcher = this.matcher(rhs);
return function (node) {
if (node.type !== "BinaryExpression") { return undefined; }
var opM = opMatcher(node.operator);
var lhsM = lhsMatcher(node.left);
var rhsM = rhsMatcher(node.right);
return combineMatches(opM, lhsM, rhsM);
};
}
/**
#### (unary op value)
Matches `UnaryExpression`.
Also shorthand version works for `!` and `~`: `(~ ?foo)` is the same as `(unary ~ ?foo)`.
*/
function unaryMatcher(operator, value) {
/* jshint validthis:true */
assertArguments("unary", 2, arguments, 1);
operator = operator || "?";
value = value || "?";
assert(_.isString(operator), "unary operator should be string expr");
var opMatcher = operatorMatcher(operator, validUnaryOperators);
var valueMatcher = this.matcher(value);
return function (node) {
if (node.type !== "UnaryExpression") { return undefined; }
var opM = opMatcher(node.operator);
var valueM = valueMatcher(node.argument);
return combineMatches(opM, valueM);
};
}
/**
#### (update op value)
Matches `UpdateExpression`.
You might want to use `postfix` and `prefix` though.
*/
function updateMatcher(prefix, operator, value) {
/* jshint validthis:true */
assertArguments("update/postfix/prefix", 2, arguments, 1);
operator = operator || "?";
value = value || "?";
assert(_.isString(operator), "update operator should be string expr");
var opMatcher = operatorMatcher(operator, validUpdateOperators);
var valueMatcher = this.matcher(value);
return function (node) {
if (node.type !== "UpdateExpression") { return undefined; }
if (prefix !== undefined && node.prefix !== prefix) { return undefined; }
var opM = opMatcher(node.operator);
var valueM = valueMatcher(node.argument);
return combineMatches(opM, valueM);
};
}
/**
#### (assign op var value)
Matches `AssignmentExpression`.
*/
function assignMatcher(operator, variable, value) {
/* jshint validthis:true */
assertArguments("assign", 3, arguments);
operator = operator || "?";
variable = variable || "?";
value = value || "?";
assert(_.isString(operator), "assignment operator should be string expr");
var opMatcher = operatorMatcher(operator, validAssignmentOperators);
var variableMatcher = this.matcher(variable);
var valueMatcher = this.matcher(value);
return function (node) {
if (node.type !== "AssignmentExpression") { return undefined; }
var opM = opMatcher(node.operator);
var variableM = variableMatcher(node.left);
var valueM = valueMatcher(node.right);
return combineMatches(opM, variableM, valueM);
};
}
/**
#### (member object property)
Matches `MemberExpression`.
- (property object property) matches non computed expressions, i.e. `foo.bar`.
- (subscript object property) matches computed expressions i.e. `foo[bar]`.
*/
function memberMatcher(computed, object, property) {
/* jshint validthis:true */
assertArguments("member/property/subscript", 2, arguments, 1);
object = object || "?";
property = property || "?";
var objectMatcher = matcher(object);
var propertyMatcher = this.matcher(property);
return function (node) {
if (node.type !== "MemberExpression") { return undefined; }
if (computed !== undefined && node.computed !== computed) { return undefined; }
var objectM = objectMatcher(node.object);
var propertyM = propertyMatcher(node.property);
return combineMatches(objectM, propertyM);
};
}
/**
#### (lookup var.name)
Helper macro for nested variable access.
`(lookup foo.bar.baz)` is equivalent to `(property (property foo bar) baz)`.
The `foo.bar.baz` will work as `(lookup foo.bar.baz)` as well.
*/
function lookupMatcher(varname) {
assert(_.isString(varname), "lookup -- takes one string argument");
// split into parts and build an s-expression
var parts = varname.split(".");
var sexpr = parts.reduce(function (prev, next) {
return ["property", prev, next];
});
return matcher(sexpr);
}
/**
#### (throw ex)
Matches `ThrowStatement`.
*/
function throwMatcher(ex) {
/* jshint validthis:true */
assertArguments("throw", 1, arguments);
ex = ex || "?";
var exMatcher = this.matcher(ex);
return function (node) {
if (node.type !== "ThrowStatement") { return undefined; }
return exMatcher(node.argument);
};
}
/**
#### (ternary test con alt)
Matches `ConditionalExpression`.
*/
function ternaryMatcher(test, con, alt) {
/* jshint validthis:true */
assertArguments("ternary", 3, arguments);
test = test || "?";
con = con || "?";
alt = alt || "?";
var testMatcher = this.matcher(test);
var consequentMatcher = this.matcher(con);
var alternateMatcher = this.matcher(alt);
return function (node) {
if (node.type !== "ConditionalExpression") { return undefined; }
var testM = testMatcher(node.test);
var consequentM = consequentMatcher(node.consequent);
var alternateM = alternateMatcher(node.alternate);
return combineMatches(testM, consequentM, alternateM);
};
}
// memoized patterns

@@ -900,3 +296,3 @@ var matchPatterns = {};

```
You may compile submatchers with `this.matcher(sexpr)` and combine their results with `this.combineMatches`.

@@ -930,43 +326,4 @@ `this.assertArguments` checks argument (rator) count, to help validate pattern grammar.

/**
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style.
Add unit tests for any new or changed functionality.
Lint and test your code using [Grunt](http://gruntjs.com/).
Use `grunt mochacov` to generate coverage report with blanket,
or `istanbul cover grunt simplemocha` to do coverage with istanbul.
## Release History
- 0.0.11 User-provided patterns
- fixed installing on Windows
- assignment pattern
- anonymous matchers
- 0.0.10 ident pattern
- 0.0.9 Boolean patterns
- 0.0.8 Even more rands
- unary and update expressions
- drop `literal-` prefix (eg plain `string` now)
- shorthand binary op syntax `(+ a b)`
- shorthand lookup syntax
- 0.0.7 jsgrep, third try
- 0.0.6 jsgrep, second try
- 0.0.5 jsgrep
- also new expression
- 0.0.4 Binary and throw
- 0.0.3 More rands
- call dotted syntax
- literals
- expr - expression statement
- use grunt-literate to generate README.md
- 0.0.2 Dev setup
- 0.0.1 Preview release
## License
Copyright (c) 2013 Oleg Grenrus.
Licensed under the BSD3 license.
*/
/// plain ../CONTRIBUTING.md
/// plain ../CHANGELOG.md
/// plain ../LICENSE
{
"name": "jsstana",
"description": "s-expression match patterns for Mozilla Parser AST",
"version": "0.0.11",
"version": "0.0.12",
"homepage": "https://github.com/phadej/jsstana",

@@ -21,3 +21,3 @@ "author": {

"type": "BSD3",
"url": "https://github.com/phadej/jsstana/blob/master/LICENSE-BSD3"
"url": "https://github.com/phadej/jsstana/blob/master/LICENSE"
}

@@ -40,10 +40,9 @@ ],

"devDependencies": {
"grunt-contrib-jshint": "~0.6.4",
"grunt-contrib-jshint": "~0.7.1",
"grunt-contrib-nodeunit": "~0.2.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-simple-mocha": "~0.4.0",
"grunt-mocha-cov": "0.0.7",
"grunt-literate": "~0.1.1",
"grunt-literate": "~0.1.3",
"grunt": "~0.4.1",
"escodegen": "0.0.27"
"escodegen": "0.0.28"
},

@@ -57,5 +56,6 @@ "keywords": [],

"esprima": "~1.0.4",
"estraverse": "~1.3.2",
"colors": "~0.6.2"
"estraverse": "~1.4.0",
"colors": "~0.6.2",
"levenshtein": "~1.0.2"
}
}

@@ -1,5 +0,10 @@

# jsstana [![Build Status](https://secure.travis-ci.org/phadej/jsstana.png?branch=master)](http://travis-ci.org/phadej/jsstana)
# jsstana
s-expression match patterns for [Mozilla Parser AST](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)
> s-expression match patterns for [Mozilla Parser AST](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)
[![Build Status](https://secure.travis-ci.org/phadej/jsstana.png?branch=master)](http://travis-ci.org/phadej/jsstana)
[![NPM version](https://badge.fury.io/js/jsstana.png)](http://badge.fury.io/js/jsstana)
[![Dependency Status](https://gemnasium.com/phadej/jsstana.png)](https://gemnasium.com/phadej/jsstana)
[![Code Climate](https://codeclimate.com/github/phadej/jsstana.png)](https://codeclimate.com/github/phadej/jsstana)
## Synopsis

@@ -28,12 +33,14 @@

# find assertArguments calls with 4 arguments
% jsgrep '(call assertArguments ? ? ? ?)' lib
jsstana.js:224: assertArguments("true/false/null/infinity/nan/undefined", 0, arguments, 1);
jsstana.js:255: assertArguments("literal", 1, arguments, 1);
jsstana.js:485: assertArguments("member/property/subscript", 2, arguments, 1);
% jsgrep '(call ?.assertArguments ? ? ? ?)' lib
matchers/literal.js:25: this.assertArguments("true/false/null/infinity/nan/undefined", 0, arguments, 1);
matchers/literal.js:111: this.assertArguments("literal", 1, arguments, 1);
matchers/member.js:18: that.assertArguments("member/property/subscript", 2, arguments, 1);
matchers/operator.js:63: that.assertArguments(ratorName, 3, arguments, 3);
matchers/operator.js:98: that.assertArguments("unary", 2, arguments, 1);
matchers/operator.js:128: that.assertArguments("update/postfix/prefix", 2, arguments, 1);
matchers/simple.js:7: this.assertArguments(rator, 1, arguments, 3);
```
## Documentation
## Pattern syntax
### Pattern syntax
#### (not pattern)

@@ -51,2 +58,18 @@

#### (call callee arg0...argn)
Matches `CallExpression`.
`(call fun arg1 arg2)` matches exact amount of arguments,
for arbitrary arguments use
`(call fun . ?)` or similar dotted list syntax.
#### (ident name)
Matches `Identifier`.
#### (var name init)
Matches `VariableDeclarator`.
#### (null-node)

@@ -56,6 +79,2 @@

#### (return value)
Matches `ReturnStatement`.
#### (literal value)

@@ -65,3 +84,4 @@

There are some additional version:
There are some additional version::
- `(string value)` - string values

@@ -78,22 +98,28 @@ - `(number value)` - number values

#### (var name init)
#### (return value)
Matches `VariableDeclarator`.
Matches `ReturnStatement`.
#### (ident name)
#### (expression expr)
Matches `Identifier`.
Matches expression statement, `ExpressionStatement`.
#### (call callee arg0...argn)
#### (throw ex)
Matches `CallExpression`.
Matches `ThrowStatement`.
`(call fun arg1 arg2)` matches exact amount of arguments,
for arbitrary arguments use
`(call fun . ?)` or similar dotted list syntax.
#### (member object property)
#### (expression expr)
Matches `MemberExpression`.
Matches expression statement, `ExpressionStatement`.
- (property object property) matches non computed expressions, i.e. `foo.bar`.
- (subscript object property) matches computed expressions i.e. `foo[bar]`.
#### (lookup var.sub.name)
Helper macro for nested variable access.
`(lookup foo.bar.baz)` is equivalent to `(property (property foo bar) baz)`.
The atom `foo.bar.baz` works as `(lookup foo.bar.baz)`.
#### (binary op lhs rhs)

@@ -121,20 +147,2 @@

#### (member object property)
Matches `MemberExpression`.
- (property object property) matches non computed expressions, i.e. `foo.bar`.
- (subscript object property) matches computed expressions i.e. `foo[bar]`.
#### (lookup var.name)
Helper macro for nested variable access.
`(lookup foo.bar.baz)` is equivalent to `(property (property foo bar) baz)`.
The `foo.bar.baz` will work as `(lookup foo.bar.baz)` as well.
#### (throw ex)
Matches `ThrowStatement`.
#### (ternary test con alt)

@@ -144,2 +152,4 @@

## API
### match(pattern, node)

@@ -184,40 +194,69 @@

## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style.
Add unit tests for any new or changed functionality.
Lint and test your code using [Grunt](http://gruntjs.com/).
Use `grunt mochacov` to generate coverage report with blanket,
or `istanbul cover grunt simplemocha` to do coverage with istanbul.
- Add unit tests for any new or changed functionality.
- Lint and test your code using [Grunt](http://gruntjs.com/).
- Use `istanbul cover grunt simplemocha` to run tests with coverage with [istanbul](http://gotwarlost.github.io/istanbul/).
- Create a pull request
## Release History
- 0.0.12 Code reogranization
- 0.0.11 User-provided patterns
- fixed installing on Windows
- assignment pattern
- anonymous matchers
- fixed installing on Windows
- assignment pattern
- anonymous matchers
- 0.0.10 ident pattern
- 0.0.9 Boolean patterns
- 0.0.8 Even more rands
- unary and update expressions
- drop `literal-` prefix (eg plain `string` now)
- shorthand binary op syntax `(+ a b)`
- shorthand lookup syntax
- unary and update expressions
- drop `literal-` prefix (eg plain `string` now)
- shorthand binary op syntax `(+ a b)`
- shorthand lookup syntax
- 0.0.7 jsgrep, third try
- 0.0.6 jsgrep, second try
- 0.0.5 jsgrep
- also new expression
- also new expression
- 0.0.4 Binary and throw
- 0.0.3 More rands
- call dotted syntax
- literals
- expr - expression statement
- use grunt-literate to generate README.md
- call dotted syntax
- literals
- expr - expression statement
- use grunt-literate to generate README.md
- 0.0.2 Dev setup
- 0.0.1 Preview release
## License
Copyright (c) 2013 Oleg Grenrus.
Licensed under the BSD3 license.
Copyright Oleg Grenrus 2013
All rights reserved.
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.
* Neither the name of Oleg Grenrus nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
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 THE COPYRIGHT
OWNER OR CONTRIBUTORS 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.

@@ -15,2 +15,8 @@ /* global describe:true, it:true */

it("throws if invalid rator is found, suggests", function () {
assert.throws(function () {
jsstana.match("(cal)");
});
});
it("throws if invalid s-expression is passed", function () {

@@ -17,0 +23,0 @@ assert.throws(function () {

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