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.2 to 0.0.3

test/expr.js

49

Gruntfile.js

@@ -51,2 +51,5 @@ "use strict";

},
literate: {
"README.md": "lib/jsstana.js",
},
});

@@ -59,50 +62,6 @@

grunt.loadNpmTasks("grunt-mocha-cov");
grunt.loadNpmTasks("grunt-literate");
// Default task.
grunt.registerTask("default", ["jshint", "simplemocha"]);
// use esprima to generate README.md from source
grunt.registerTask("readme", "Generate README.md", function () {
var src = "./lib/jsstana.js";
var dest = "README.md";
var esprima = require("esprima");
var _ = require("underscore");
var content = grunt.file.read(src);
var syntax = esprima.parse(content, { comment: true });
var comments = syntax.comments;
function isWhitespace(str) {
return (/^\s*$/).test(str);
}
var mdContent = _.reduce(comments, function (acc, comment) {
if (comment.type === "Block" && comment.value[0] === "*") {
// block comment starting with /**
var value = comment.value.slice(1);
var lines = value.split(/\n/);
var first = _.find(lines, function (line) { return !isWhitespace(line); } );
var indent = first ? /^(\s*)/.exec(first)[1] : "";
// unindent lines
lines = _.map(lines, function (line) {
if (line.indexOf(indent) === 0) {
return line.replace(indent, "");
} else if (isWhitespace(line)) {
return "";
} else {
return line;
}
});
return acc + lines.join("\n");
} else {
// do nothing with rest
return acc;
}
}, "");
grunt.file.write(dest, mdContent);
});
};

@@ -65,3 +65,3 @@ /**

p.seq(lexemeP("("), p.repeat(function () { return sexprP; }), lexemeP(")")).onMatch(function (arr) { return arr[1]; }),
lexemeP(p.regex(/[a-zA-Z\?\.\-][a-zA-Z0-9_\?\.\-]*/)).onMatch(_.first),
lexemeP(p.regex(/[a-zA-Z\?\.\-\/*+<>=!][a-zA-Z0-9_\?\.\-\/*+<>+!]*/)).onMatch(_.first),
lexemeP(p.regex(/[0-9]+/)).onMatch(function (m) { return parseInt(_.first(m), 10); } )

@@ -135,2 +135,3 @@ );

"call": callMatcher,
"expr": expressionMatcher,
"member": memberMatcher.bind(undefined, undefined),

@@ -141,3 +142,14 @@ "property": memberMatcher.bind(undefined, false),

"ternary": ternaryMatcher,
"undefined": undefinedMatcher,
"literal": literalMatcher.bind(undefined, "any"),
"literal-string": literalMatcher.bind(undefined, "string"),
"literal-number": literalMatcher.bind(undefined, "number"),
"literal-bool": literalMatcher.bind(undefined, "bool"),
"literal-regexp": literalMatcher.bind(undefined, "regexp"),
"null": literalBuiltinMatcher.bind(undefined, "null"),
"true": literalBuiltinMatcher.bind(undefined, "true"),
"false": literalBuiltinMatcher.bind(undefined, "false"),
"infinity": literalBuiltinMatcher.bind(undefined, "infinity"),
"nan": literalBuiltinMatcher.bind(undefined, "nan"),
"undefined": literalBuiltinMatcher.bind(undefined, "undefined"),
"null-node": nullNodeMatcher,
};

@@ -162,10 +174,10 @@

/**
#### (undefined)
#### (null-node)
matches `undefined` node
Matches `undefined` node.
*/
function undefinedMatcher() {
assertArguments("undefined", 0, arguments);
function nullNodeMatcher() {
assertArguments("null-node", 0, arguments);
return function (node) {
return node === undefined ? {} : undefined;
return node === null ? {} : undefined;
};

@@ -195,5 +207,126 @@ }

/**
#### (literal value)
Matches `Literal`.
There are some additional version:
- `(literal-string value)` - string values
- `(literal-number value)` - number values
- `(literal-bool value)` - boolean values
- `(literal-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
Matches `VariableDeclarator`.
*/

@@ -224,2 +357,6 @@ function varMatcher(id, init) {

Matches `CallExpression`.
`(call fun arg1 arg2)` matches exact amount of arguments,
for arbitrary arguments use
`(call fun . ?)` or similar dotted list syntax.
*/

@@ -230,4 +367,28 @@ function callMatcher(callee) {

var calleeMatcher = matcher(callee);
var argumentMatchers = _.toArray(arguments).slice(1).map(matcher);
var args = _.toArray(arguments).slice(1);
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);
return function (node) {

@@ -238,2 +399,3 @@ if (node.type !== "CallExpression") { return undefined; }

if (calleeM === undefined) { return undefined; }
if (!dotted && argumentMatchers.length !== node.arguments.length) { return undefined; }

@@ -247,2 +409,6 @@ for (var i = 0; i < argumentMatchers.length; i++) {

if (dottedM) {
calleeM = _.extend(calleeM, dottedM(node.arguments.slice(argumentMatchers.length)));
}
return calleeM;

@@ -253,2 +419,20 @@ };

/**
#### (expression expr)
Matches expression statement, `ExpressionStatement`.
*/
function expressionMatcher(expr) {
assertArguments("expr", 1, arguments);
expr = expr || "?";
var exprMatcher = matcher(expr);
return function (node) {
if (node.type !== "ExpressionStatement") { return undefined; }
return exprMatcher(node.expression);
};
}
/**
#### (member object property)

@@ -378,2 +562,7 @@

- 0.0.3 More rands
- call dotted syntax
- literals
- expr - expression statement
- use grunt-literate to generate README.md
- 0.0.2 Dev setup

@@ -380,0 +569,0 @@ - 0.0.1 Preview release

{
"name": "jsstana",
"description": "s-expression match patterns for Mozilla Parser AST",
"version": "0.0.2",
"version": "0.0.3",
"homepage": "https://github.com/phadej/jsstana",

@@ -41,2 +41,3 @@ "author": {

"grunt-mocha-cov": "0.0.7",
"grunt-literate": "~0.1.1",
"grunt": "~0.4.1",

@@ -43,0 +44,0 @@ "esprima": "~1.0.4",

@@ -1,2 +0,1 @@

# jsstana [![Build Status](https://secure.travis-ci.org/phadej/jsstana.png?branch=master)](http://travis-ci.org/phadej/jsstana)

@@ -28,5 +27,5 @@

#### (undefined)
#### (null-node)
matches `undefined` node
Matches `undefined` node.

@@ -37,5 +36,21 @@ #### (return value)

#### (literal value)
Matches `Literal`.
There are some additional version:
- `(literal-string value)` - string values
- `(literal-number value)` - number values
- `(literal-bool value)` - boolean values
- `(literal-regexp value)` - regular expressions
- `(true)` - matches `true`
- `(false)` - matches `false`
- `(null)` - matches `null`
- `(infinity)` - matches `Infinity`
- `(nan)` - matches `NaN`
- `(undefined)` - matches `undefined`
#### (var name init)
Matches `VariableDeclarator
Matches `VariableDeclarator`.

@@ -46,2 +61,10 @@ #### (call callee arg0...argn)

`(call fun arg1 arg2)` matches exact amount of arguments,
for arbitrary arguments use
`(call fun . ?)` or similar dotted list syntax.
#### (expression expr)
Matches expression statement, `ExpressionStatement`.
#### (member object property)

@@ -78,3 +101,2 @@

## Contributing

@@ -88,2 +110,7 @@

- 0.0.3 More rands
- call dotted syntax
- literals
- expr - expression statement
- use grunt-literate to generate README.md
- 0.0.2 Dev setup

@@ -96,1 +123,2 @@ - 0.0.1 Preview release

Licensed under the BSD3 license.

@@ -57,3 +57,3 @@ /* global describe:true, it:true */

it("consecutive arguments match arguments, more arguments than specified", function () {
it("matches exact amout of argument", function () {
var syntax = esprima.parse("module.fun(foo, bar, baz)");

@@ -65,10 +65,10 @@ var node = syntax.body[0].expression;

assert.deepEqual(matcher(syntax), undefined);
assert.deepEqual(matcher(node), {});
assert.deepEqual(matcher(node), undefined);
});
it("can use (undefined)", function () {
var syntax = esprima.parse("module.fun(foo, bar)");
it("can use (call fun . ?) to match rest arguments", function () {
var syntax = esprima.parse("module.fun(foo, bar, baz, quux)");
var node = syntax.body[0].expression;
var matcher = jsstana.match("(call (lookup module.fun) foo bar (undefined))");
var matcher = jsstana.match("(call (lookup module.fun) . ?)");

@@ -79,11 +79,17 @@ assert.deepEqual(matcher(syntax), undefined);

it("can use (undefined)", function () {
var syntax = esprima.parse("module.fun(foo, bar, baz)");
it("can use (call . ?dotted-syntax) to capture rest arguments", function () {
var syntax = esprima.parse("module.fun(foo, bar, baz, quux)");
var node = syntax.body[0].expression;
var matcher = jsstana.match("(call (lookup module.fun) foo bar (undefined))");
var matcher = jsstana.match("(call (lookup module.fun) foo ? . ?rest)");
assert.deepEqual(matcher(syntax), undefined);
assert.deepEqual(matcher(node), undefined);
assert.deepEqual(matcher(node).rest.length, 2);
});
it("should have pattern variable after dot", function () {
assert.throws(function () {
jsstana.match("(call foo . foo)");
});
});
});

@@ -73,3 +73,12 @@ /* global describe:true, it:true */

});
it("can use (null-node) to match uninitialized declrations", function () {
var syntax = esprima.parse("var foo;");
var node = syntax.body[0].declarations[0];
var matcher = jsstana.match("(var foo (null-node))");
assert.deepEqual(matcher(syntax), undefined);
assert.deepEqual(matcher(node), {});
});
});
});
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