更新前端静态网页获取方式,放弃使用后端获取api

This commit is contained in:
2025-09-09 10:47:51 +08:00
parent 6889ca37e5
commit 44a4f1bae1
25558 changed files with 2463152 additions and 153 deletions

60
frontend/node_modules/jsonpath/.jscsrc generated vendored Normal file
View File

@@ -0,0 +1,60 @@
{
"disallowSpacesInNamedFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"disallowEmptyBlocks": true,
"disallowSpacesInsideParentheses": true,
"disallowQuotedKeysInObjects": true,
"disallowSpaceAfterObjectKeys": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowSpaceBeforePostfixUnaryOperators": true,
"disallowSpaceBeforeBinaryOperators": [
","
],
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true,
"disallowYodaConditions": true,
"disallowKeywords": [ "with" ],
"disallowMultipleLineBreaks": true,
"requireSpaceBeforeBlockStatements": true,
"requireParenthesesAroundIIFE": true,
"requireSpacesInConditionalExpression": true,
"disallowMultipleVarDecl": true,
"requireBlocksOnNewline": 1,
"requireCommaBeforeLineBreak": true,
"requireSpaceBeforeBinaryOperators": true,
"requireSpaceAfterBinaryOperators": true,
"requireLineFeedAtFileEnd": true,
"requireCapitalizedConstructors": true,
"requireDotNotation": true,
"requireSpacesInForStatement": true,
"requireCurlyBraces": [
"do"
],
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"case",
"return",
"try",
"catch",
"typeof"
],
"safeContextKeyword": "self",
"validateLineBreaks": "LF",
"validateIndentation": 2
}

9
frontend/node_modules/jsonpath/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"node": true,
"undef": true,
"unused": true,
"lastsemic": true,
"-W058": false, /* don't require parentheses for no-arg constructors */
"-W054": false, /* use Function constructor responsibly */
"-W033": false /* let jscs deal with semicolons */
}

3
frontend/node_modules/jsonpath/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,3 @@
language: node_js
node_js:
- "0.10"

1
frontend/node_modules/jsonpath/Dockerfile generated vendored Normal file
View File

@@ -0,0 +1 @@
FROM node:0.11-onbuild

83
frontend/node_modules/jsonpath/Gruntfile.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
var Browserify = require('browserify');
var bresolve = require('browser-resolve');
patchResolve();
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
outputFolder: ".",
browserify: {
main: {
src: ['index.js'],
dest: '<%= outputFolder %>/<%= pkg.name %>.js',
options: {
browserifyOptions: { standalone: '<%= pkg.name %>' },
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n',
alias: {
"jsonpath": "./index.js"
},
require: [
/**
* When running in Node, we require('./aesprim') and that module takes care of monkey-patching esprima
* using resolve, path finding, etc...
* Anyways, Browserify doesn't support "resolve", so we need to trick the module. We'll actually be
* returning a verbatim, non-modified "esprima" when the code runs require('./aesprim').
* That is ok because we will modify the "esprima" source code right after the bundle process, via
* the postBundleCB callback.
*/
["esprima", {expose: "./aesprim"}]
],
ignore: [
'file',
'system',
'source-map',
'estraverse',
'escodegen',
'underscore',
'reflect',
'JSONSelect',
'./lib/aesprim.js'
//'assert' //can't remove because of lib/index.js,
],
postBundleCB: function(err, src, next) {
/**
* This is ugly, but we need to make "esprima" understand '@' as a valid character.
* It's either this or bundle a copy of the library with those few bytes of changes.
*/
src = src.toString("utf8").replace(/(function isIdentifierStart\(ch\) {\s+return)/m, '$1 (ch == 0x40) || ');
next(err, new Buffer(src, "utf8"));
}
}
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n'
},
build: {
src: '<%= outputFolder %>/<%= pkg.name %>.js',
dest: '<%= outputFolder %>/<%= pkg.name %>.min.js'
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify')
grunt.registerTask('default', ['browserify', 'uglify']);
};
function patchResolve() {
var _createDeps = Browserify.prototype._createDeps;
Browserify.prototype._createDeps = function() {
var returnValue = _createDeps.apply(this, arguments);
this._bresolve = function(id, opts, cb) {
opts.browser = 'alias';
return bresolve(id, opts, cb);
};
return returnValue;
}
}

7
frontend/node_modules/jsonpath/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2014-2016 David Chester <david@fmail.co.uk>
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.

216
frontend/node_modules/jsonpath/README.md generated vendored Executable file
View File

@@ -0,0 +1,216 @@
[![Build Status](https://travis-ci.org/dchester/jsonpath.png?branch=master)](https://travis-ci.org/dchester/jsonpath)
# jsonpath
Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.
## Query Example
```javascript
var cities = [
{ name: "London", "population": 8615246 },
{ name: "Berlin", "population": 3517424 },
{ name: "Madrid", "population": 3165235 },
{ name: "Rome", "population": 2870528 }
];
var jp = require('jsonpath');
var names = jp.query(cities, '$..name');
// [ "London", "Berlin", "Madrid", "Rome" ]
```
## Install
Install from npm:
```bash
$ npm install jsonpath
```
## JSONPath Syntax
Here are syntax and examples adapted from [Stefan Goessner's original post](http://goessner.net/articles/JsonPath/) introducing JSONPath in 2007.
JSONPath | Description
-----------------|------------
`$` | The root object/element
`@` | The current object/element
`.` | Child member operator
`..` | Recursive descendant operator; JSONPath borrows this syntax from E4X
`*` | Wildcard matching all objects/elements regardless their names
`[]` | Subscript operator
`[,]` | Union operator for alternate names or array indices as a set
`[start:end:step]` | Array slice operator borrowed from ES4 / Python
`?()` | Applies a filter (script) expression via static evaluation
`()` | Script expression via static evaluation
Given this sample data set, see example expressions below:
```javascript
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}, {
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}, {
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}, {
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
```
Example JSONPath expressions:
JSONPath | Description
------------------------------|------------
`$.store.book[*].author` | The authors of all books in the store
`$..author` | All authors
`$.store.*` | All things in store, which are some books and a red bicycle
`$.store..price` | The price of everything in the store
`$..book[2]` | The third book
`$..book[(@.length-1)]` | The last book via script subscript
`$..book[-1:]` | The last book via slice
`$..book[0,1]` | The first two books via subscript union
`$..book[:2]` | The first two books via subscript array slice
`$..book[?(@.isbn)]` | Filter all books with isbn number
`$..book[?(@.price<10)]` | Filter all books cheaper than 10
`$..book[?(@.price==8.95)]` | Filter all books that cost 8.95
`$..book[?(@.price<30 && @.category=="fiction")]` | Filter all fiction books cheaper than 30
`$..*` | All members of JSON structure
## Methods
#### jp.query(obj, pathExpression[, count])
Find elements in `obj` matching `pathExpression`. Returns an array of elements that satisfy the provided JSONPath expression, or an empty array if none were matched. Returns only first `count` elements if specified.
```javascript
var authors = jp.query(data, '$..author');
// [ 'Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien' ]
```
#### jp.paths(obj, pathExpression[, count])
Find paths to elements in `obj` matching `pathExpression`. Returns an array of element paths that satisfy the provided JSONPath expression. Each path is itself an array of keys representing the location within `obj` of the matching element. Returns only first `count` paths if specified.
```javascript
var paths = jp.paths(data, '$..author');
// [
// ['$', 'store', 'book', 0, 'author'] },
// ['$', 'store', 'book', 1, 'author'] },
// ['$', 'store', 'book', 2, 'author'] },
// ['$', 'store', 'book', 3, 'author'] }
// ]
```
#### jp.nodes(obj, pathExpression[, count])
Find elements and their corresponding paths in `obj` matching `pathExpression`. Returns an array of node objects where each node has a `path` containing an array of keys representing the location within `obj`, and a `value` pointing to the matched element. Returns only first `count` nodes if specified.
```javascript
var nodes = jp.nodes(data, '$..author');
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
// ]
```
#### jp.value(obj, pathExpression[, newValue])
Returns the value of the first element matching `pathExpression`. If `newValue` is provided, sets the value of the first matching element and returns the new value.
#### jp.parent(obj, pathExpression)
Returns the parent of the first matching element.
#### jp.apply(obj, pathExpression, fn)
Runs the supplied function `fn` on each matching element, and replaces each matching element with the return value from the function. The function accepts the value of the matching element as its only parameter. Returns matching nodes with their updated values.
```javascript
var nodes = jp.apply(data, '$..author', function(value) { return value.toUpperCase() });
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'NIGEL REES' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'EVELYN WAUGH' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'HERMAN MELVILLE' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. TOLKIEN' }
// ]
```
#### jp.parse(pathExpression)
Parse the provided JSONPath expression into path components and their associated operations.
```javascript
var path = jp.parse('$..author');
// [
// { expression: { type: 'root', value: '$' } },
// { expression: { type: 'identifier', value: 'author' }, operation: 'member', scope: 'descendant' }
// ]
```
#### jp.stringify(path)
Returns a path expression in string form, given a path. The supplied path may either be a flat array of keys, as returned by `jp.nodes` for example, or may alternatively be a fully parsed path expression in the form of an array of path components as returned by `jp.parse`.
```javascript
var pathExpression = jp.stringify(['$', 'store', 'book', 0, 'author']);
// "$.store.book[0].author"
```
## Differences from Original Implementation
This implementation aims to be compatible with Stefan Goessner's original implementation with a few notable exceptions described below.
#### Evaluating Script Expressions
Script expressions (i.e, `(...)` and `?(...)`) are statically evaluated via [static-eval](https://github.com/substack/static-eval) rather than using the underlying script engine directly. That means both that the scope is limited to the instance variable (`@`), and only simple expressions (with no side effects) will be valid. So for example, `?(@.length>10)` will be just fine to match arrays with more than ten elements, but `?(process.exit())` will not get evaluated since `process` would yield a `ReferenceError`. This method is even safer than `vm.runInNewContext`, since the script engine itself is more limited and entirely distinct from the one running the application code. See more details in the [implementation](https://github.com/substack/static-eval/blob/master/index.js) of the evaluator.
#### Grammar
This project uses a formal BNF [grammar](https://github.com/dchester/jsonpath/blob/master/lib/grammar.js) to parse JSONPath expressions, an attempt at reverse-engineering the intent of the original implementation, which parses via a series of creative regular expressions. The original regex approach can sometimes be forgiving for better or for worse (e.g., `$['store]` => `$['store']`), and in other cases, can be just plain wrong (e.g. `[` => `$`).
#### Other Minor Differences
As a result of using a real parser and static evaluation, there are some arguable bugs in the original library that have not been carried through here:
- strings in subscripts may now be double-quoted
- final `step` arguments in slice operators may now be negative
- script expressions may now contain `.` and `@` characters not referring to instance variables
- subscripts no longer act as character slices on string elements
- non-ascii non-word characters are no-longer valid in member identifier names; use quoted subscript strings instead (e.g., `$['$']` instead of `$.$`)
- unions now yield real unions with no duplicates rather than concatenated results
## License
[MIT](LICENSE)

View File

@@ -0,0 +1,8 @@
var JisonParser = require('jison').Parser;
var grammar = require('../lib/grammar');
var parser = new JisonParser(grammar);
source = parser.generate()
console.log(source)

5
frontend/node_modules/jsonpath/fig.yml generated vendored Normal file
View File

@@ -0,0 +1,5 @@
test:
build: .
command: node /usr/src/app/node_modules/.bin/mocha -u tdd test/
volumes:
- .:/usr/src/app

721
frontend/node_modules/jsonpath/generated/parser.js generated vendored Normal file
View File

@@ -0,0 +1,721 @@
/* parser generated by jison 0.4.13 */
/*
Returns a Parser object of the following structure:
Parser: {
yy: {}
}
Parser.prototype: {
yy: {},
trace: function(),
symbols_: {associative list: name ==> number},
terminals_: {associative list: number ==> name},
productions_: [...],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
table: [...],
defaultActions: {...},
parseError: function(str, hash),
parse: function(input),
lexer: {
EOF: 1,
parseError: function(str, hash),
setInput: function(input),
input: function(),
unput: function(str),
more: function(),
less: function(n),
pastInput: function(),
upcomingInput: function(),
showPosition: function(),
test_match: function(regex_match_array, rule_index),
next: function(),
lex: function(),
begin: function(condition),
popState: function(),
_currentRules: function(),
topState: function(),
pushState: function(condition),
options: {
ranges: boolean (optional: true ==> token location info will include a .range[] member)
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
},
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
rules: [...],
conditions: {associative list: name ==> set},
}
}
token location info (@$, _$, etc.): {
first_line: n,
last_line: n,
first_column: n,
last_column: n,
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
}
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
text: (matched text)
token: (the produced terminal token, if any)
line: (yylineno)
}
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
loc: (yylloc)
expected: (string describing the set of expected tokens)
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var parser = (function(){
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"JSON_PATH":3,"DOLLAR":4,"PATH_COMPONENTS":5,"LEADING_CHILD_MEMBER_EXPRESSION":6,"PATH_COMPONENT":7,"MEMBER_COMPONENT":8,"SUBSCRIPT_COMPONENT":9,"CHILD_MEMBER_COMPONENT":10,"DESCENDANT_MEMBER_COMPONENT":11,"DOT":12,"MEMBER_EXPRESSION":13,"DOT_DOT":14,"STAR":15,"IDENTIFIER":16,"SCRIPT_EXPRESSION":17,"INTEGER":18,"END":19,"CHILD_SUBSCRIPT_COMPONENT":20,"DESCENDANT_SUBSCRIPT_COMPONENT":21,"[":22,"SUBSCRIPT":23,"]":24,"SUBSCRIPT_EXPRESSION":25,"SUBSCRIPT_EXPRESSION_LIST":26,"SUBSCRIPT_EXPRESSION_LISTABLE":27,",":28,"STRING_LITERAL":29,"ARRAY_SLICE":30,"FILTER_EXPRESSION":31,"QQ_STRING":32,"Q_STRING":33,"$accept":0,"$end":1},
terminals_: {2:"error",4:"DOLLAR",12:"DOT",14:"DOT_DOT",15:"STAR",16:"IDENTIFIER",17:"SCRIPT_EXPRESSION",18:"INTEGER",19:"END",22:"[",24:"]",28:",",30:"ARRAY_SLICE",31:"FILTER_EXPRESSION",32:"QQ_STRING",33:"Q_STRING"},
productions_: [0,[3,1],[3,2],[3,1],[3,2],[5,1],[5,2],[7,1],[7,1],[8,1],[8,1],[10,2],[6,1],[11,2],[13,1],[13,1],[13,1],[13,1],[13,1],[9,1],[9,1],[20,3],[21,4],[23,1],[23,1],[26,1],[26,3],[27,1],[27,1],[27,1],[25,1],[25,1],[25,1],[29,1],[29,1]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */
/**/) {
/* this == yyval */
if (!yy.ast) {
yy.ast = _ast;
_ast.initialize();
}
var $0 = $$.length - 1;
switch (yystate) {
case 1:yy.ast.set({ expression: { type: "root", value: $$[$0] } }); yy.ast.unshift(); return yy.ast.yield()
break;
case 2:yy.ast.set({ expression: { type: "root", value: $$[$0-1] } }); yy.ast.unshift(); return yy.ast.yield()
break;
case 3:yy.ast.unshift(); return yy.ast.yield()
break;
case 4:yy.ast.set({ operation: "member", scope: "child", expression: { type: "identifier", value: $$[$0-1] }}); yy.ast.unshift(); return yy.ast.yield()
break;
case 5:
break;
case 6:
break;
case 7:yy.ast.set({ operation: "member" }); yy.ast.push()
break;
case 8:yy.ast.set({ operation: "subscript" }); yy.ast.push()
break;
case 9:yy.ast.set({ scope: "child" })
break;
case 10:yy.ast.set({ scope: "descendant" })
break;
case 11:
break;
case 12:yy.ast.set({ scope: "child", operation: "member" })
break;
case 13:
break;
case 14:yy.ast.set({ expression: { type: "wildcard", value: $$[$0] } })
break;
case 15:yy.ast.set({ expression: { type: "identifier", value: $$[$0] } })
break;
case 16:yy.ast.set({ expression: { type: "script_expression", value: $$[$0] } })
break;
case 17:yy.ast.set({ expression: { type: "numeric_literal", value: parseInt($$[$0]) } })
break;
case 18:
break;
case 19:yy.ast.set({ scope: "child" })
break;
case 20:yy.ast.set({ scope: "descendant" })
break;
case 21:
break;
case 22:
break;
case 23:
break;
case 24:$$[$0].length > 1? yy.ast.set({ expression: { type: "union", value: $$[$0] } }) : this.$ = $$[$0]
break;
case 25:this.$ = [$$[$0]]
break;
case 26:this.$ = $$[$0-2].concat($$[$0])
break;
case 27:this.$ = { expression: { type: "numeric_literal", value: parseInt($$[$0]) } }; yy.ast.set(this.$)
break;
case 28:this.$ = { expression: { type: "string_literal", value: $$[$0] } }; yy.ast.set(this.$)
break;
case 29:this.$ = { expression: { type: "slice", value: $$[$0] } }; yy.ast.set(this.$)
break;
case 30:this.$ = { expression: { type: "wildcard", value: $$[$0] } }; yy.ast.set(this.$)
break;
case 31:this.$ = { expression: { type: "script_expression", value: $$[$0] } }; yy.ast.set(this.$)
break;
case 32:this.$ = { expression: { type: "filter_expression", value: $$[$0] } }; yy.ast.set(this.$)
break;
case 33:this.$ = $$[$0]
break;
case 34:this.$ = $$[$0]
break;
}
},
table: [{3:1,4:[1,2],6:3,13:4,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9]},{1:[3]},{1:[2,1],5:10,7:11,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,3],5:21,7:11,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,12],12:[2,12],14:[2,12],22:[2,12]},{1:[2,14],12:[2,14],14:[2,14],22:[2,14]},{1:[2,15],12:[2,15],14:[2,15],22:[2,15]},{1:[2,16],12:[2,16],14:[2,16],22:[2,16]},{1:[2,17],12:[2,17],14:[2,17],22:[2,17]},{1:[2,18],12:[2,18],14:[2,18],22:[2,18]},{1:[2,2],7:22,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,5],12:[2,5],14:[2,5],22:[2,5]},{1:[2,7],12:[2,7],14:[2,7],22:[2,7]},{1:[2,8],12:[2,8],14:[2,8],22:[2,8]},{1:[2,9],12:[2,9],14:[2,9],22:[2,9]},{1:[2,10],12:[2,10],14:[2,10],22:[2,10]},{1:[2,19],12:[2,19],14:[2,19],22:[2,19]},{1:[2,20],12:[2,20],14:[2,20],22:[2,20]},{13:23,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9]},{13:24,15:[1,5],16:[1,6],17:[1,7],18:[1,8],19:[1,9],22:[1,25]},{15:[1,29],17:[1,30],18:[1,33],23:26,25:27,26:28,27:32,29:34,30:[1,35],31:[1,31],32:[1,36],33:[1,37]},{1:[2,4],7:22,8:12,9:13,10:14,11:15,12:[1,18],14:[1,19],20:16,21:17,22:[1,20]},{1:[2,6],12:[2,6],14:[2,6],22:[2,6]},{1:[2,11],12:[2,11],14:[2,11],22:[2,11]},{1:[2,13],12:[2,13],14:[2,13],22:[2,13]},{15:[1,29],17:[1,30],18:[1,33],23:38,25:27,26:28,27:32,29:34,30:[1,35],31:[1,31],32:[1,36],33:[1,37]},{24:[1,39]},{24:[2,23]},{24:[2,24],28:[1,40]},{24:[2,30]},{24:[2,31]},{24:[2,32]},{24:[2,25],28:[2,25]},{24:[2,27],28:[2,27]},{24:[2,28],28:[2,28]},{24:[2,29],28:[2,29]},{24:[2,33],28:[2,33]},{24:[2,34],28:[2,34]},{24:[1,41]},{1:[2,21],12:[2,21],14:[2,21],22:[2,21]},{18:[1,33],27:42,29:34,30:[1,35],32:[1,36],33:[1,37]},{1:[2,22],12:[2,22],14:[2,22],22:[2,22]},{24:[2,26],28:[2,26]}],
defaultActions: {27:[2,23],29:[2,30],30:[2,31],31:[2,32]},
parseError: function parseError(str, hash) {
if (hash.recoverable) {
this.trace(str);
} else {
throw new Error(str);
}
},
parse: function parse(input) {
var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
var args = lstack.slice.call(arguments, 1);
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == 'undefined') {
this.lexer.yylloc = {};
}
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === 'function') {
this.parseError = this.yy.parseError;
} else {
this.parseError = Object.getPrototypeOf(this).parseError;
}
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || EOF;
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == 'undefined') {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === 'undefined' || !action.length || !action[0]) {
var errStr = '';
expected = [];
for (p in table[state]) {
if (this.terminals_[p] && p > TERROR) {
expected.push('\'' + this.terminals_[p] + '\'');
}
}
if (this.lexer.showPosition) {
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + this.lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
} else {
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
}
this.parseError(errStr, {
text: this.lexer.match,
token: this.terminals_[symbol] || symbol,
line: this.lexer.yylineno,
loc: yyloc,
expected: expected
});
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0) {
recovering--;
}
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = {
first_line: lstack[lstack.length - (len || 1)].first_line,
last_line: lstack[lstack.length - 1].last_line,
first_column: lstack[lstack.length - (len || 1)].first_column,
last_column: lstack[lstack.length - 1].last_column
};
if (ranges) {
yyval._$.range = [
lstack[lstack.length - (len || 1)].range[0],
lstack[lstack.length - 1].range[1]
];
}
r = this.performAction.apply(yyval, [
yytext,
yyleng,
yylineno,
this.yy,
action[1],
vstack,
lstack
].concat(args));
if (typeof r !== 'undefined') {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}};
var _ast = {
initialize: function() {
this._nodes = [];
this._node = {};
this._stash = [];
},
set: function(props) {
for (var k in props) this._node[k] = props[k];
return this._node;
},
node: function(obj) {
if (arguments.length) this._node = obj;
return this._node;
},
push: function() {
this._nodes.push(this._node);
this._node = {};
},
unshift: function() {
this._nodes.unshift(this._node);
this._node = {};
},
yield: function() {
var _nodes = this._nodes;
this.initialize();
return _nodes;
}
};
/* generated by jison-lex 0.2.1 */
var lexer = (function(){
var lexer = {
EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
// resets the lexer, sets new input
setInput:function (input) {
this._input = input;
this._more = this._backtrack = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {
first_line: 1,
first_column: 0,
last_line: 1,
last_column: 0
};
if (this.options.ranges) {
this.yylloc.range = [0,0];
}
this.offset = 0;
return this;
},
// consumes and returns one char from the input
input:function () {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) {
this.yylloc.range[1]++;
}
this._input = this._input.slice(1);
return ch;
},
// unshifts one char (or a string) into the input
unput:function (ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) {
this.yylineno -= lines.length - 1;
}
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
this.yyleng = this.yytext.length;
return this;
},
// When called from action, caches matched text and appends it on next action
more:function () {
this._more = true;
return this;
},
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
reject:function () {
if (this.options.backtrack_lexer) {
this._backtrack = true;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
return this;
},
// retain first n characters of the match
less:function (n) {
this.unput(this.match.slice(n));
},
// displays already matched input, i.e. for error messages
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
// displays upcoming input, i.e. for error messages
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
// displays the character position where the lexing error occurred, i.e. for error messages
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
// test the lexed token: return FALSE when not a match, otherwise return token
test_match:function (match, indexed_rule) {
var token,
lines,
backup;
if (this.options.backtrack_lexer) {
// save context
backup = {
yylineno: this.yylineno,
yylloc: {
first_line: this.yylloc.first_line,
last_line: this.last_line,
first_column: this.yylloc.first_column,
last_column: this.yylloc.last_column
},
yytext: this.yytext,
match: this.match,
matches: this.matches,
matched: this.matched,
yyleng: this.yyleng,
offset: this.offset,
_more: this._more,
_input: this._input,
yy: this.yy,
conditionStack: this.conditionStack.slice(0),
done: this.done
};
if (this.options.ranges) {
backup.yylloc.range = this.yylloc.range.slice(0);
}
}
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno += lines.length;
}
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ?
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._backtrack = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) {
this.done = false;
}
if (token) {
return token;
} else if (this._backtrack) {
// recover context
for (var k in backup) {
this[k] = backup[k];
}
return false; // rule action called reject() implying the next rule should be tested instead.
}
return false;
},
// return next match in input
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) {
this.done = true;
}
var token,
match,
tempMatch,
index;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (this.options.backtrack_lexer) {
token = this.test_match(tempMatch, rules[i]);
if (token !== false) {
return token;
} else if (this._backtrack) {
match = false;
continue; // rule action called reject() implying a rule MISmatch.
} else {
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
} else if (!this.options.flex) {
break;
}
}
}
if (match) {
token = this.test_match(match, rules[index]);
if (token !== false) {
return token;
}
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
},
// return next match that has a token
lex:function lex() {
var r = this.next();
if (r) {
return r;
} else {
return this.lex();
}
},
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
begin:function begin(condition) {
this.conditionStack.push(condition);
},
// pop the previously active lexer condition state off the condition stack
popState:function popState() {
var n = this.conditionStack.length - 1;
if (n > 0) {
return this.conditionStack.pop();
} else {
return this.conditionStack[0];
}
},
// produce the lexer rule set which is active for the currently active lexer condition state
_currentRules:function _currentRules() {
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
} else {
return this.conditions["INITIAL"].rules;
}
},
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
topState:function topState(n) {
n = this.conditionStack.length - 1 - Math.abs(n || 0);
if (n >= 0) {
return this.conditionStack[n];
} else {
return "INITIAL";
}
},
// alias for begin(condition)
pushState:function pushState(condition) {
this.begin(condition);
},
// return the number of states currently on the stack
stateStackSize:function stateStackSize() {
return this.conditionStack.length;
},
options: {},
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START
/**/) {
var YYSTATE=YY_START;
switch($avoiding_name_collisions) {
case 0:return 4
break;
case 1:return 14
break;
case 2:return 12
break;
case 3:return 15
break;
case 4:return 16
break;
case 5:return 22
break;
case 6:return 24
break;
case 7:return 28
break;
case 8:return 30
break;
case 9:return 18
break;
case 10:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 32;
break;
case 11:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 33;
break;
case 12:return 17
break;
case 13:return 31
break;
}
},
rules: [/^(?:\$)/,/^(?:\.\.)/,/^(?:\.)/,/^(?:\*)/,/^(?:[a-zA-Z_]+[a-zA-Z0-9_]*)/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?:((-?(?:0|[1-9][0-9]*)))?\:((-?(?:0|[1-9][0-9]*)))?(\:((-?(?:0|[1-9][0-9]*)))?)?)/,/^(?:(-?(?:0|[1-9][0-9]*)))/,/^(?:"(?:\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*")/,/^(?:'(?:\\['bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^'\\])*')/,/^(?:\(.+?\)(?=\]))/,/^(?:\?\(.+?\)(?=\]))/],
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}
};
return lexer;
})();
parser.lexer = lexer;
function Parser () {
this.yy = {};
}
Parser.prototype = parser;parser.Parser = Parser;
return new Parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
exports.parser = parser;
exports.Parser = parser.Parser;
exports.parse = function () { return parser.parse.apply(parser, arguments); };
exports.main = function commonjsMain(args) {
if (!args[1]) {
console.log('Usage: '+args[0]+' FILE');
process.exit(1);
}
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
return exports.parser.parse(source);
};
if (typeof module !== 'undefined' && require.main === module) {
exports.main(process.argv.slice(1));
}
}

4
frontend/node_modules/jsonpath/include/action.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
if (!yy.ast) {
yy.ast = _ast;
_ast.initialize();
}

34
frontend/node_modules/jsonpath/include/module.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
var _ast = {
initialize: function() {
this._nodes = [];
this._node = {};
this._stash = [];
},
set: function(props) {
for (var k in props) this._node[k] = props[k];
return this._node;
},
node: function(obj) {
if (arguments.length) this._node = obj;
return this._node;
},
push: function() {
this._nodes.push(this._node);
this._node = {};
},
unshift: function() {
this._nodes.unshift(this._node);
this._node = {};
},
yield: function() {
var _nodes = this._nodes;
this.initialize();
return _nodes;
}
};

1
frontend/node_modules/jsonpath/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/index');

6842
frontend/node_modules/jsonpath/jsonpath.js generated vendored Normal file

File diff suppressed because one or more lines are too long

4
frontend/node_modules/jsonpath/jsonpath.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
../esprima/bin/esparse.js

View File

@@ -0,0 +1 @@
../esprima/bin/esvalidate.js

View File

@@ -0,0 +1,24 @@
**Esprima** ([esprima.org](http://esprima.org), BSD license) is a high performance,
standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
parser written in ECMAScript (also popularly known as
[JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript)).
Esprima is created and maintained by [Ariya Hidayat](http://twitter.com/ariyahidayat),
with the help of [many contributors](https://github.com/ariya/esprima/contributors).
### Features
- Full support for ECMAScript 5.1 ([ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm))
- Sensible [syntax tree format](http://esprima.org/doc/index.html#ast) compatible with Mozilla
[Parser AST](https://developer.mozilla.org/en/SpiderMonkey/Parser_API)
- Optional tracking of syntax node location (index-based and line-column)
- Heavily tested (> 650 [unit tests](http://esprima.org/test/) with [full code coverage](http://esprima.org/test/coverage.html))
- [Partial support](http://esprima.org/doc/es6.html) for ECMAScript 6
Esprima serves as a **building block** for some JavaScript
language tools, from [code instrumentation](http://esprima.org/demo/functiontrace.html)
to [editor autocompletion](http://esprima.org/demo/autocomplete.html).
Esprima runs on many popular web browsers, as well as other ECMAScript platforms such as
[Rhino](http://www.mozilla.org/rhino), [Nashorn](http://openjdk.java.net/projects/nashorn/), and [Node.js](https://npmjs.org/package/esprima).
For more information, check the web site [esprima.org](http://esprima.org).

View File

@@ -0,0 +1,127 @@
#!/usr/bin/env node
/*
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
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 <COPYRIGHT HOLDER> 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 sloppy:true node:true rhino:true */
var fs, esprima, fname, content, options, syntax;
if (typeof require === 'function') {
fs = require('fs');
esprima = require('esprima');
} else if (typeof load === 'function') {
try {
load('esprima.js');
} catch (e) {
load('../esprima.js');
}
}
// Shims to Node.js objects when running under Rhino.
if (typeof console === 'undefined' && typeof process === 'undefined') {
console = { log: print };
fs = { readFileSync: readFile };
process = { argv: arguments, exit: quit };
process.argv.unshift('esparse.js');
process.argv.unshift('rhino');
}
function showUsage() {
console.log('Usage:');
console.log(' esparse [options] file.js');
console.log();
console.log('Available options:');
console.log();
console.log(' --comment Gather all line and block comments in an array');
console.log(' --loc Include line-column location info for each syntax node');
console.log(' --range Include index-based range for each syntax node');
console.log(' --raw Display the raw value of literals');
console.log(' --tokens List all tokens in an array');
console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)');
console.log(' -v, --version Shows program version');
console.log();
process.exit(1);
}
if (process.argv.length <= 2) {
showUsage();
}
options = {};
process.argv.splice(2).forEach(function (entry) {
if (entry === '-h' || entry === '--help') {
showUsage();
} else if (entry === '-v' || entry === '--version') {
console.log('ECMAScript Parser (using Esprima version', esprima.version, ')');
console.log();
process.exit(0);
} else if (entry === '--comment') {
options.comment = true;
} else if (entry === '--loc') {
options.loc = true;
} else if (entry === '--range') {
options.range = true;
} else if (entry === '--raw') {
options.raw = true;
} else if (entry === '--tokens') {
options.tokens = true;
} else if (entry === '--tolerant') {
options.tolerant = true;
} else if (entry.slice(0, 2) === '--') {
console.log('Error: unknown option ' + entry + '.');
process.exit(1);
} else if (typeof fname === 'string') {
console.log('Error: more than one input file.');
process.exit(1);
} else {
fname = entry;
}
});
if (typeof fname !== 'string') {
console.log('Error: no input file.');
process.exit(1);
}
// Special handling for regular expression literal since we need to
// convert it to a string literal, otherwise it will be decoded
// as object "{}" and the regular expression would be lost.
function adjustRegexLiteral(key, value) {
if (key === 'value' && value instanceof RegExp) {
value = value.toString();
}
return value;
}
try {
content = fs.readFileSync(fname, 'utf-8');
syntax = esprima.parse(content, options);
console.log(JSON.stringify(syntax, adjustRegexLiteral, 4));
} catch (e) {
console.log('Error: ' + e.message);
process.exit(1);
}

View File

@@ -0,0 +1,199 @@
#!/usr/bin/env node
/*
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
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 <COPYRIGHT HOLDER> 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 sloppy:true plusplus:true node:true rhino:true */
/*global phantom:true */
var fs, system, esprima, options, fnames, count;
if (typeof esprima === 'undefined') {
// PhantomJS can only require() relative files
if (typeof phantom === 'object') {
fs = require('fs');
system = require('system');
esprima = require('./esprima');
} else if (typeof require === 'function') {
fs = require('fs');
esprima = require('esprima');
} else if (typeof load === 'function') {
try {
load('esprima.js');
} catch (e) {
load('../esprima.js');
}
}
}
// Shims to Node.js objects when running under PhantomJS 1.7+.
if (typeof phantom === 'object') {
fs.readFileSync = fs.read;
process = {
argv: [].slice.call(system.args),
exit: phantom.exit
};
process.argv.unshift('phantomjs');
}
// Shims to Node.js objects when running under Rhino.
if (typeof console === 'undefined' && typeof process === 'undefined') {
console = { log: print };
fs = { readFileSync: readFile };
process = { argv: arguments, exit: quit };
process.argv.unshift('esvalidate.js');
process.argv.unshift('rhino');
}
function showUsage() {
console.log('Usage:');
console.log(' esvalidate [options] file.js');
console.log();
console.log('Available options:');
console.log();
console.log(' --format=type Set the report format, plain (default) or junit');
console.log(' -v, --version Print program version');
console.log();
process.exit(1);
}
if (process.argv.length <= 2) {
showUsage();
}
options = {
format: 'plain'
};
fnames = [];
process.argv.splice(2).forEach(function (entry) {
if (entry === '-h' || entry === '--help') {
showUsage();
} else if (entry === '-v' || entry === '--version') {
console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
console.log();
process.exit(0);
} else if (entry.slice(0, 9) === '--format=') {
options.format = entry.slice(9);
if (options.format !== 'plain' && options.format !== 'junit') {
console.log('Error: unknown report format ' + options.format + '.');
process.exit(1);
}
} else if (entry.slice(0, 2) === '--') {
console.log('Error: unknown option ' + entry + '.');
process.exit(1);
} else {
fnames.push(entry);
}
});
if (fnames.length === 0) {
console.log('Error: no input file.');
process.exit(1);
}
if (options.format === 'junit') {
console.log('<?xml version="1.0" encoding="UTF-8"?>');
console.log('<testsuites>');
}
count = 0;
fnames.forEach(function (fname) {
var content, timestamp, syntax, name;
try {
content = fs.readFileSync(fname, 'utf-8');
if (content[0] === '#' && content[1] === '!') {
content = '//' + content.substr(2, content.length);
}
timestamp = Date.now();
syntax = esprima.parse(content, { tolerant: true });
if (options.format === 'junit') {
name = fname;
if (name.lastIndexOf('/') >= 0) {
name = name.slice(name.lastIndexOf('/') + 1);
}
console.log('<testsuite name="' + fname + '" errors="0" ' +
' failures="' + syntax.errors.length + '" ' +
' tests="' + syntax.errors.length + '" ' +
' time="' + Math.round((Date.now() - timestamp) / 1000) +
'">');
syntax.errors.forEach(function (error) {
var msg = error.message;
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
console.log(' <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
' time="0">');
console.log(' <error type="SyntaxError" message="' + error.message + '">' +
error.message + '(' + name + ':' + error.lineNumber + ')' +
'</error>');
console.log(' </testcase>');
});
console.log('</testsuite>');
} else if (options.format === 'plain') {
syntax.errors.forEach(function (error) {
var msg = error.message;
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
msg = fname + ':' + error.lineNumber + ': ' + msg;
console.log(msg);
++count;
});
}
} catch (e) {
++count;
if (options.format === 'junit') {
console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
console.log(' <error type="ParseError" message="' + e.message + '">' +
e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
')</error>');
console.log(' </testcase>');
console.log('</testsuite>');
} else {
console.log('Error: ' + e.message);
}
}
});
if (options.format === 'junit') {
console.log('</testsuites>');
}
if (count > 0) {
process.exit(1);
}
if (count === 0 && typeof phantom === 'object') {
process.exit(0);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,83 @@
{
"name": "esprima",
"description": "ECMAScript parsing infrastructure for multipurpose analysis",
"homepage": "http://esprima.org",
"main": "esprima.js",
"bin": {
"esparse": "./bin/esparse.js",
"esvalidate": "./bin/esvalidate.js"
},
"version": "1.2.2",
"files": [
"bin",
"test/run.js",
"test/runner.js",
"test/test.js",
"test/compat.js",
"test/reflect.js",
"esprima.js"
],
"engines": {
"node": ">=0.4.0"
},
"author": {
"name": "Ariya Hidayat",
"email": "ariya.hidayat@gmail.com"
},
"maintainers": [{
"name": "Ariya Hidayat",
"email": "ariya.hidayat@gmail.com",
"web": "http://ariya.ofilabs.com"
}],
"repository": {
"type": "git",
"url": "http://github.com/ariya/esprima.git"
},
"bugs": {
"url": "http://issues.esprima.org"
},
"licenses": [{
"type": "BSD",
"url": "http://github.com/ariya/esprima/raw/master/LICENSE.BSD"
}],
"devDependencies": {
"jslint": "~0.1.9",
"eslint": "~0.4.3",
"jscs": "~1.2.4",
"istanbul": "~0.2.6",
"complexity-report": "~0.6.1",
"regenerate": "~0.5.4",
"unicode-6.3.0": "~0.1.0",
"json-diff": "~0.3.1",
"optimist": "~0.6.0"
},
"keywords": [
"ast",
"ecmascript",
"javascript",
"parser",
"syntax"
],
"scripts": {
"generate-regex": "node tools/generate-identifier-regex.js",
"test": "npm run-script lint && node test/run.js && npm run-script coverage && npm run-script complexity",
"lint": "npm run-script check-version && npm run-script eslint && npm run-script jscs && npm run-script jslint",
"check-version": "node tools/check-version.js",
"eslint": "node node_modules/eslint/bin/eslint.js esprima.js",
"jscs": "node node_modules/.bin/jscs esprima.js",
"jslint": "node node_modules/jslint/bin/jslint.js esprima.js",
"coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
"analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/runner.js",
"check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement 100 --branch 100 --function 100",
"complexity": "npm run-script analyze-complexity && npm run-script check-complexity",
"analyze-complexity": "node tools/list-complexity.js",
"check-complexity": "node node_modules/complexity-report/src/cli.js --maxcc 14 --silent -l -w esprima.js",
"benchmark": "node test/benchmarks.js",
"benchmark-quick": "node test/benchmarks.js quick"
}
}

View File

@@ -0,0 +1,241 @@
/*
Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
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 <COPYRIGHT HOLDER> 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 node: true */
/*global document: true, window:true, esprima: true, testReflect: true */
var runTests;
function getContext(esprima, reportCase, reportFailure) {
'use strict';
var Reflect, Pattern;
// Maps Mozilla Reflect object to our Esprima parser.
Reflect = {
parse: function (code) {
var result;
reportCase(code);
try {
result = esprima.parse(code);
} catch (error) {
result = error;
}
return result;
}
};
// This is used by Reflect test suite to match a syntax tree.
Pattern = function (obj) {
var pattern;
// Poor man's deep object cloning.
pattern = JSON.parse(JSON.stringify(obj));
// Special handling for regular expression literal since we need to
// convert it to a string literal, otherwise it will be decoded
// as object "{}" and the regular expression would be lost.
if (obj.type && obj.type === 'Literal') {
if (obj.value instanceof RegExp) {
pattern = {
type: obj.type,
value: obj.value.toString()
};
}
}
// Special handling for branch statement because SpiderMonkey
// prefers to put the 'alternate' property before 'consequent'.
if (obj.type && obj.type === 'IfStatement') {
pattern = {
type: pattern.type,
test: pattern.test,
consequent: pattern.consequent,
alternate: pattern.alternate
};
}
// Special handling for do while statement because SpiderMonkey
// prefers to put the 'test' property before 'body'.
if (obj.type && obj.type === 'DoWhileStatement') {
pattern = {
type: pattern.type,
body: pattern.body,
test: pattern.test
};
}
function adjustRegexLiteralAndRaw(key, value) {
if (key === 'value' && value instanceof RegExp) {
value = value.toString();
} else if (key === 'raw' && typeof value === "string") {
// Ignore Esprima-specific 'raw' property.
return undefined;
}
return value;
}
if (obj.type && (obj.type === 'Program')) {
pattern.assert = function (tree) {
var actual, expected;
actual = JSON.stringify(tree, adjustRegexLiteralAndRaw, 4);
expected = JSON.stringify(obj, null, 4);
if (expected !== actual) {
reportFailure(expected, actual);
}
};
}
return pattern;
};
return {
Reflect: Reflect,
Pattern: Pattern
};
}
if (typeof window !== 'undefined') {
// Run all tests in a browser environment.
runTests = function () {
'use strict';
var total = 0,
failures = 0;
function setText(el, str) {
if (typeof el.innerText === 'string') {
el.innerText = str;
} else {
el.textContent = str;
}
}
function reportCase(code) {
var report, e;
report = document.getElementById('report');
e = document.createElement('pre');
e.setAttribute('class', 'code');
setText(e, code);
report.appendChild(e);
total += 1;
}
function reportFailure(expected, actual) {
var report, e;
failures += 1;
report = document.getElementById('report');
e = document.createElement('p');
setText(e, 'Expected');
report.appendChild(e);
e = document.createElement('pre');
e.setAttribute('class', 'expected');
setText(e, expected);
report.appendChild(e);
e = document.createElement('p');
setText(e, 'Actual');
report.appendChild(e);
e = document.createElement('pre');
e.setAttribute('class', 'actual');
setText(e, actual);
report.appendChild(e);
}
setText(document.getElementById('version'), esprima.version);
window.setTimeout(function () {
var tick, context = getContext(esprima, reportCase, reportFailure);
tick = new Date();
testReflect(context.Reflect, context.Pattern);
tick = (new Date()) - tick;
if (failures > 0) {
document.getElementById('status').className = 'alert-box alert';
setText(document.getElementById('status'), total + ' tests. ' +
'Failures: ' + failures + '. ' + tick + ' ms');
} else {
document.getElementById('status').className = 'alert-box success';
setText(document.getElementById('status'), total + ' tests. ' +
'No failure. ' + tick + ' ms');
}
}, 11);
};
} else {
(function (global) {
'use strict';
var esprima = require('../esprima'),
tick,
total = 0,
failures = [],
header,
current,
context;
function reportCase(code) {
total += 1;
current = code;
}
function reportFailure(expected, actual) {
failures.push({
source: current,
expected: expected.toString(),
actual: actual.toString()
});
}
context = getContext(esprima, reportCase, reportFailure);
tick = new Date();
require('./reflect').testReflect(context.Reflect, context.Pattern);
tick = (new Date()) - tick;
header = total + ' tests. ' + failures.length + ' failures. ' +
tick + ' ms';
if (failures.length) {
console.error(header);
failures.forEach(function (failure) {
console.error(failure.source + ': Expected\n ' +
failure.expected.split('\n').join('\n ') +
'\nto match\n ' + failure.actual);
});
} else {
console.log(header);
}
process.exit(failures.length === 0 ? 0 : 1);
}(this));
}
/* vim: set sw=4 ts=4 et tw=80 : */

View File

@@ -0,0 +1,422 @@
// This is modified from Mozilla Reflect.parse test suite (the file is located
// at js/src/tests/js1_8_5/extensions/reflect-parse.js in the source tree).
//
// Some notable changes:
// * Removed unsupported features (destructuring, let, comprehensions...).
// * Removed tests for E4X (ECMAScript for XML).
// * Removed everything related to builder.
// * Enclosed every 'Pattern' construct with a scope.
// * Tweaked some expected tree to remove generator field.
// * Removed the test for bug 632030 and bug 632024.
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
(function (exports) {
function testReflect(Reflect, Pattern) {
function program(elts) { return Pattern({ type: "Program", body: elts }) }
function exprStmt(expr) { return Pattern({ type: "ExpressionStatement", expression: expr }) }
function throwStmt(expr) { return Pattern({ type: "ThrowStatement", argument: expr }) }
function returnStmt(expr) { return Pattern({ type: "ReturnStatement", argument: expr }) }
function yieldExpr(expr) { return Pattern({ type: "YieldExpression", argument: expr }) }
function lit(val) { return Pattern({ type: "Literal", value: val }) }
var thisExpr = Pattern({ type: "ThisExpression" });
function funDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration",
id: id,
params: params,
defaults: [],
body: body,
rest: null,
generator: false,
expression: false
}) }
function genFunDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration",
id: id,
params: params,
defaults: [],
body: body,
rest: null,
generator: false,
expression: false
}) }
function declarator(id, init) { return Pattern({ type: "VariableDeclarator", id: id, init: init }) }
function varDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" }) }
function letDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" }) }
function constDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" }) }
function ident(name) { return Pattern({ type: "Identifier", name: name }) }
function dotExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: false, object: obj, property: id }) }
function memExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: true, object: obj, property: id }) }
function forStmt(init, test, update, body) { return Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body }) }
function forInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false }) }
function forEachInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true }) }
function breakStmt(lab) { return Pattern({ type: "BreakStatement", label: lab }) }
function continueStmt(lab) { return Pattern({ type: "ContinueStatement", label: lab }) }
function blockStmt(body) { return Pattern({ type: "BlockStatement", body: body }) }
var emptyStmt = Pattern({ type: "EmptyStatement" });
function ifStmt(test, cons, alt) { return Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons }) }
function labStmt(lab, stmt) { return Pattern({ type: "LabeledStatement", label: lab, body: stmt }) }
function withStmt(obj, stmt) { return Pattern({ type: "WithStatement", object: obj, body: stmt }) }
function whileStmt(test, stmt) { return Pattern({ type: "WhileStatement", test: test, body: stmt }) }
function doStmt(stmt, test) { return Pattern({ type: "DoWhileStatement", test: test, body: stmt }) }
function switchStmt(disc, cases) { return Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases }) }
function caseClause(test, stmts) { return Pattern({ type: "SwitchCase", test: test, consequent: stmts }) }
function defaultClause(stmts) { return Pattern({ type: "SwitchCase", test: null, consequent: stmts }) }
function catchClause(id, guard, body) { if (guard) { return Pattern({ type: "GuardedCatchClause", param: id, guard: guard, body: body }) } else { return Pattern({ type: "CatchClause", param: id, body: body }) } }
function tryStmt(body, guarded, catches, fin) { return Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handlers: catches, finalizer: fin }) }
function letStmt(head, body) { return Pattern({ type: "LetStatement", head: head, body: body }) }
function funExpr(id, args, body, gen) { return Pattern({ type: "FunctionExpression",
id: id,
params: args,
defaults: [],
body: body,
rest: null,
generator: false,
expression: false
}) }
function genFunExpr(id, args, body) { return Pattern({ type: "FunctionExpression",
id: id,
params: args,
defaults: [],
body: body,
rest: null,
generator: false,
expression: false
}) }
function unExpr(op, arg) { return Pattern({ type: "UnaryExpression", operator: op, argument: arg, prefix: true }) }
function binExpr(op, left, right) { return Pattern({ type: "BinaryExpression", operator: op, left: left, right: right }) }
function aExpr(op, left, right) { return Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right }) }
function updExpr(op, arg, prefix) { return Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix }) }
function logExpr(op, left, right) { return Pattern({ type: "LogicalExpression", operator: op, left: left, right: right }) }
function condExpr(test, cons, alt) { return Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt }) }
function seqExpr(exprs) { return Pattern({ type: "SequenceExpression", expressions: exprs }) }
function newExpr(callee, args) { return Pattern({ type: "NewExpression", callee: callee, arguments: args }) }
function callExpr(callee, args) { return Pattern({ type: "CallExpression", callee: callee, arguments: args }) }
function arrExpr(elts) { return Pattern({ type: "ArrayExpression", elements: elts }) }
function objExpr(elts) { return Pattern({ type: "ObjectExpression", properties: elts }) }
function objProp(key, value, kind) { return Pattern({ type: "Property", key: key, value: value, kind: kind }) }
function arrPatt(elts) { return Pattern({ type: "ArrayPattern", elements: elts }) }
function objPatt(elts) { return Pattern({ type: "ObjectPattern", properties: elts }) }
function localSrc(src) { return "(function(){ " + src + " })" }
function localPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([patt])))]) }
function blockSrc(src) { return "(function(){ { " + src + " } })" }
function blockPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))]) }
function assertBlockStmt(src, patt) {
blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
}
function assertBlockExpr(src, patt) {
assertBlockStmt(src, exprStmt(patt));
}
function assertBlockDecl(src, patt, builder) {
blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
}
function assertLocalStmt(src, patt) {
localPatt(patt).assert(Reflect.parse(localSrc(src)));
}
function assertLocalExpr(src, patt) {
assertLocalStmt(src, exprStmt(patt));
}
function assertLocalDecl(src, patt) {
localPatt(patt).assert(Reflect.parse(localSrc(src)));
}
function assertGlobalStmt(src, patt, builder) {
program([patt]).assert(Reflect.parse(src, {builder: builder}));
}
function assertGlobalExpr(src, patt, builder) {
program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
//assertStmt(src, exprStmt(patt));
}
function assertGlobalDecl(src, patt) {
program([patt]).assert(Reflect.parse(src));
}
function assertProg(src, patt) {
program(patt).assert(Reflect.parse(src));
}
function assertStmt(src, patt) {
assertLocalStmt(src, patt);
assertGlobalStmt(src, patt);
assertBlockStmt(src, patt);
}
function assertExpr(src, patt) {
assertLocalExpr(src, patt);
assertGlobalExpr(src, patt);
assertBlockExpr(src, patt);
}
function assertDecl(src, patt) {
assertLocalDecl(src, patt);
assertGlobalDecl(src, patt);
assertBlockDecl(src, patt);
}
function assertError(src, errorType) {
try {
Reflect.parse(src);
} catch (e) {
return;
}
throw new Error("expected " + errorType.name + " for " + uneval(src));
}
// general tests
// NB: These are useful but for now jit-test doesn't do I/O reliably.
//program(_).assert(Reflect.parse(snarf('data/flapjax.txt')));
//program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt')));
//program(_).assert(Reflect.parse(snarf('data/prototype.js')));
//program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js')));
//program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js')));
// declarations
assertDecl("var x = 1, y = 2, z = 3",
varDecl([declarator(ident("x"), lit(1)),
declarator(ident("y"), lit(2)),
declarator(ident("z"), lit(3))]));
assertDecl("var x, y, z",
varDecl([declarator(ident("x"), null),
declarator(ident("y"), null),
declarator(ident("z"), null)]));
assertDecl("function foo() { }",
funDecl(ident("foo"), [], blockStmt([])));
assertDecl("function foo() { return 42 }",
funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
// Bug 591437: rebound args have their defs turned into uses
assertDecl("function f(a) { function a() { } }",
funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
assertDecl("function f(a,b,c) { function b() { } }",
funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
// expressions
assertExpr("true", lit(true));
assertExpr("false", lit(false));
assertExpr("42", lit(42));
assertExpr("(/asdf/)", lit(/asdf/));
assertExpr("this", thisExpr);
assertExpr("foo", ident("foo"));
assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
assertExpr("(++x)", updExpr("++", ident("x"), true));
assertExpr("(x++)", updExpr("++", ident("x"), false));
assertExpr("(+x)", unExpr("+", ident("x")));
assertExpr("(-x)", unExpr("-", ident("x")));
assertExpr("(!x)", unExpr("!", ident("x")));
assertExpr("(~x)", unExpr("~", ident("x")));
assertExpr("(delete x)", unExpr("delete", ident("x")));
assertExpr("(typeof x)", unExpr("typeof", ident("x")));
assertExpr("(void x)", unExpr("void", ident("x")));
assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z")));
assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z")));
assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
assertExpr("(new Object)", newExpr(ident("Object"), []));
assertExpr("(new Object())", newExpr(ident("Object"), []));
assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
assertExpr("(String())", callExpr(ident("String"), []));
assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
assertExpr("[]", arrExpr([]));
assertExpr("[1]", arrExpr([lit(1)]));
assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
assertExpr("[1,,2,3]", arrExpr([lit(1),,lit(2),lit(3)]));
assertExpr("[1,,,2,3]", arrExpr([lit(1),,,lit(2),lit(3)]));
assertExpr("[1,,,2,,3]", arrExpr([lit(1),,,lit(2),,lit(3)]));
assertExpr("[1,,,2,,,3]", arrExpr([lit(1),,,lit(2),,,lit(3)]));
assertExpr("[,1,2,3]", arrExpr([,lit(1),lit(2),lit(3)]));
assertExpr("[,,1,2,3]", arrExpr([,,lit(1),lit(2),lit(3)]));
assertExpr("[,,,1,2,3]", arrExpr([,,,lit(1),lit(2),lit(3)]));
assertExpr("[,,,1,2,3,]", arrExpr([,,,lit(1),lit(2),lit(3)]));
assertExpr("[,,,1,2,3,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined]));
assertExpr("[,,,1,2,3,,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined,undefined]));
assertExpr("[,,,,,]", arrExpr([undefined,undefined,undefined,undefined,undefined]));
assertExpr("({})", objExpr([]));
assertExpr("({x:1})", objExpr([objProp(ident("x"), lit(1), "init")]));
assertExpr("({x:1, y:2})", objExpr([objProp(ident("x"), lit(1), "init"),
objProp(ident("y"), lit(2), "init")]));
assertExpr("({x:1, y:2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"),
objProp(ident("y"), lit(2), "init"),
objProp(ident("z"), lit(3), "init") ]));
assertExpr("({x:1, 'y':2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"),
objProp(lit("y"), lit(2), "init"),
objProp(ident("z"), lit(3), "init") ]));
assertExpr("({'x':1, 'y':2, z:3})", objExpr([objProp(lit("x"), lit(1), "init"),
objProp(lit("y"), lit(2), "init"),
objProp(ident("z"), lit(3), "init") ]));
assertExpr("({'x':1, 'y':2, 3:3})", objExpr([objProp(lit("x"), lit(1), "init"),
objProp(lit("y"), lit(2), "init"),
objProp(lit(3), lit(3), "init") ]));
// Bug 571617: eliminate constant-folding
assertExpr("2 + 3", binExpr("+", lit(2), lit(3)));
// Bug 632026: constant-folding
assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a"))));
// Bug 632056: constant-folding
program([exprStmt(ident("f")),
ifStmt(lit(1),
funDecl(ident("f"), [], blockStmt([])),
null)]).assert(Reflect.parse("f; if (1) function f(){}"));
// statements
assertStmt("throw 42", throwStmt(lit(42)));
assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
assertStmt("for (var x; y; z) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), ident("z"), breakStmt(null)));
assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), ident("y"), ident("z"), breakStmt(null)));
assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
assertStmt("for (var x; ; z) break", forStmt(varDecl([declarator(ident("x"), null)]), null, ident("z"), breakStmt(null)));
assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), null, ident("z"), breakStmt(null)));
assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
assertStmt("for (var x; y; ) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), null, breakStmt(null)));
assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([declarator(ident("x"),lit(42))]), ident("y"), null, breakStmt(null)));
assertStmt("for (var x in y) break", forInStmt(varDecl([declarator(ident("x"),null)]), ident("y"), breakStmt(null)));
assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
assertStmt("{ }", blockStmt([]));
assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
assertStmt(";", emptyStmt);
assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
ifStmt(ident("foo"),
blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
null));
assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
ifStmt(ident("foo"),
blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
exprStmt(lit(true))));
assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
switchStmt(ident("foo"),
[ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
defaultClause([ exprStmt(lit(3)) ]) ]));
assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
switchStmt(ident("foo"),
[ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
defaultClause([ exprStmt(lit(3)) ]),
caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
assertStmt("try { } catch (e) { }",
tryStmt(blockStmt([]),
[],
[ catchClause(ident("e"), null, blockStmt([])) ],
null));
assertStmt("try { } catch (e) { } finally { }",
tryStmt(blockStmt([]),
[],
[ catchClause(ident("e"), null, blockStmt([])) ],
blockStmt([])));
assertStmt("try { } finally { }",
tryStmt(blockStmt([]),
[],
[],
blockStmt([])));
// redeclarations (TOK_NAME nodes with lexdef)
assertStmt("function f() { function g() { } function g() { } }",
funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
funDecl(ident("g"), [], blockStmt([]))])));
assertStmt("function f() { function g() { } function g() { return 42 } }",
funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
assertStmt("function f() { var x = 42; var x = 43; }",
funDecl(ident("f"), [], blockStmt([varDecl([declarator(ident("x"),lit(42))]),
varDecl([declarator(ident("x"),lit(43))])])));
// getters and setters
assertExpr("({ get x() { return 42 } })",
objExpr([ objProp(ident("x"),
funExpr(null, [], blockStmt([returnStmt(lit(42))])),
"get" ) ]));
assertExpr("({ set x(v) { return 42 } })",
objExpr([ objProp(ident("x"),
funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])),
"set" ) ]));
}
exports.testReflect = testReflect;
}(typeof exports === 'undefined' ? this : exports));

View File

@@ -0,0 +1,67 @@
/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
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 <COPYRIGHT HOLDER> 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 node:true */
(function () {
'use strict';
var child = require('child_process'),
nodejs = '"' + process.execPath + '"',
ret = 0,
suites,
index;
suites = [
'runner',
'compat',
'parselibs'
];
function nextTest() {
var suite = suites[index];
if (index < suites.length) {
child.exec(nodejs + ' ./test/' + suite + '.js', function (err, stdout, stderr) {
if (stdout) {
process.stdout.write(suite + ': ' + stdout);
}
if (stderr) {
process.stderr.write(suite + ': ' + stderr);
}
if (err) {
ret = err.code;
}
index += 1;
nextTest();
});
} else {
process.exit(ret);
}
}
index = 0;
nextTest();
}());

View File

@@ -0,0 +1,495 @@
/*
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2011 Arpad Borsos <arpad.borsos@googlemail.com>
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 <COPYRIGHT HOLDER> 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 browser:true node:true */
/*global esprima:true, testFixture:true */
var runTests;
// Special handling for regular expression literal since we need to
// convert it to a string literal, otherwise it will be decoded
// as object "{}" and the regular expression would be lost.
function adjustRegexLiteral(key, value) {
'use strict';
if (key === 'value' && value instanceof RegExp) {
value = value.toString();
}
return value;
}
function NotMatchingError(expected, actual) {
'use strict';
Error.call(this, 'Expected ');
this.expected = expected;
this.actual = actual;
}
NotMatchingError.prototype = new Error();
function errorToObject(e) {
'use strict';
var msg = e.toString();
// Opera 9.64 produces an non-standard string in toString().
if (msg.substr(0, 6) !== 'Error:') {
if (typeof e.message === 'string') {
msg = 'Error: ' + e.message;
}
}
return {
index: e.index,
lineNumber: e.lineNumber,
column: e.column,
message: msg
};
}
function sortedObject(o) {
if (o === null) {
return o;
}
if (o instanceof Array) {
return o.map(sortedObject);
}
if (typeof o !== 'object') {
return o;
}
if (o instanceof RegExp) {
return o;
}
var keys = Object.keys(o);
var result = {
range: undefined,
loc: undefined
};
keys.forEach(function (key) {
if (o.hasOwnProperty(key)){
result[key] = sortedObject(o[key]);
}
});
return result;
}
function hasAttachedComment(syntax) {
var key;
for (key in syntax) {
if (key === 'leadingComments' || key === 'trailingComments') {
return true;
}
if (typeof syntax[key] === 'object' && syntax[key] !== null) {
if (hasAttachedComment(syntax[key])) {
return true;
}
}
}
return false;
}
function testParse(esprima, code, syntax) {
'use strict';
var expected, tree, actual, options, StringObject, i, len, err;
// alias, so that JSLint does not complain.
StringObject = String;
options = {
comment: (typeof syntax.comments !== 'undefined'),
range: true,
loc: true,
tokens: (typeof syntax.tokens !== 'undefined'),
raw: true,
tolerant: (typeof syntax.errors !== 'undefined'),
source: null
};
if (options.comment) {
options.attachComment = hasAttachedComment(syntax);
}
if (typeof syntax.tokens !== 'undefined') {
if (syntax.tokens.length > 0) {
options.range = (typeof syntax.tokens[0].range !== 'undefined');
options.loc = (typeof syntax.tokens[0].loc !== 'undefined');
}
}
if (typeof syntax.comments !== 'undefined') {
if (syntax.comments.length > 0) {
options.range = (typeof syntax.comments[0].range !== 'undefined');
options.loc = (typeof syntax.comments[0].loc !== 'undefined');
}
}
if (options.loc) {
options.source = syntax.loc.source;
}
syntax = sortedObject(syntax);
expected = JSON.stringify(syntax, null, 4);
try {
// Some variations of the options.
tree = esprima.parse(code, { tolerant: options.tolerant });
tree = esprima.parse(code, { tolerant: options.tolerant, range: true });
tree = esprima.parse(code, { tolerant: options.tolerant, loc: true });
tree = esprima.parse(code, options);
tree = (options.comment || options.tokens || options.tolerant) ? tree : tree.body[0];
if (options.tolerant) {
for (i = 0, len = tree.errors.length; i < len; i += 1) {
tree.errors[i] = errorToObject(tree.errors[i]);
}
}
tree = sortedObject(tree);
actual = JSON.stringify(tree, adjustRegexLiteral, 4);
// Only to ensure that there is no error when using string object.
esprima.parse(new StringObject(code), options);
} catch (e) {
throw new NotMatchingError(expected, e.toString());
}
if (expected !== actual) {
throw new NotMatchingError(expected, actual);
}
function filter(key, value) {
if (key === 'value' && value instanceof RegExp) {
value = value.toString();
}
return (key === 'loc' || key === 'range') ? undefined : value;
}
if (options.tolerant) {
return;
}
// Check again without any location info.
options.range = false;
options.loc = false;
syntax = sortedObject(syntax);
expected = JSON.stringify(syntax, filter, 4);
try {
tree = esprima.parse(code, options);
tree = (options.comment || options.tokens) ? tree : tree.body[0];
if (options.tolerant) {
for (i = 0, len = tree.errors.length; i < len; i += 1) {
tree.errors[i] = errorToObject(tree.errors[i]);
}
}
tree = sortedObject(tree);
actual = JSON.stringify(tree, filter, 4);
} catch (e) {
throw new NotMatchingError(expected, e.toString());
}
if (expected !== actual) {
throw new NotMatchingError(expected, actual);
}
}
function testTokenize(esprima, code, tokens) {
'use strict';
var options, expected, actual, tree;
options = {
comment: true,
tolerant: true,
loc: true,
range: true
};
expected = JSON.stringify(tokens, null, 4);
try {
tree = esprima.tokenize(code, options);
actual = JSON.stringify(tree, null, 4);
} catch (e) {
throw new NotMatchingError(expected, e.toString());
}
if (expected !== actual) {
throw new NotMatchingError(expected, actual);
}
}
function testError(esprima, code, exception) {
'use strict';
var i, options, expected, actual, err, handleInvalidRegexFlag, tokenize;
// Different parsing options should give the same error.
options = [
{},
{ comment: true },
{ raw: true },
{ raw: true, comment: true }
];
// If handleInvalidRegexFlag is true, an invalid flag in a regular expression
// will throw an exception. In some old version V8, this is not the case
// and hence handleInvalidRegexFlag is false.
handleInvalidRegexFlag = false;
try {
'test'.match(new RegExp('[a-z]', 'x'));
} catch (e) {
handleInvalidRegexFlag = true;
}
exception.description = exception.message.replace(/Error: Line [0-9]+: /, '');
if (exception.tokenize) {
tokenize = true;
exception.tokenize = undefined;
}
expected = JSON.stringify(exception);
for (i = 0; i < options.length; i += 1) {
try {
if (tokenize) {
esprima.tokenize(code, options[i])
} else {
esprima.parse(code, options[i]);
}
} catch (e) {
err = errorToObject(e);
err.description = e.description;
actual = JSON.stringify(err);
}
if (expected !== actual) {
// Compensate for old V8 which does not handle invalid flag.
if (exception.message.indexOf('Invalid regular expression') > 0) {
if (typeof actual === 'undefined' && !handleInvalidRegexFlag) {
return;
}
}
throw new NotMatchingError(expected, actual);
}
}
}
function testAPI(esprima, code, result) {
'use strict';
var expected, res, actual;
expected = JSON.stringify(result.result, null, 4);
try {
if (typeof result.property !== 'undefined') {
res = esprima[result.property];
} else {
res = esprima[result.call].apply(esprima, result.args);
}
actual = JSON.stringify(res, adjustRegexLiteral, 4);
} catch (e) {
throw new NotMatchingError(expected, e.toString());
}
if (expected !== actual) {
throw new NotMatchingError(expected, actual);
}
}
function runTest(esprima, code, result) {
'use strict';
if (result.hasOwnProperty('lineNumber')) {
testError(esprima, code, result);
} else if (result.hasOwnProperty('result')) {
testAPI(esprima, code, result);
} else if (result instanceof Array) {
testTokenize(esprima, code, result);
} else {
testParse(esprima, code, result);
}
}
if (typeof window !== 'undefined') {
// Run all tests in a browser environment.
runTests = function () {
'use strict';
var total = 0,
failures = 0,
category,
fixture,
source,
tick,
expected,
index,
len;
function setText(el, str) {
if (typeof el.innerText === 'string') {
el.innerText = str;
} else {
el.textContent = str;
}
}
function startCategory(category) {
var report, e;
report = document.getElementById('report');
e = document.createElement('h4');
setText(e, category);
report.appendChild(e);
}
function reportSuccess(code) {
var report, e;
report = document.getElementById('report');
e = document.createElement('pre');
e.setAttribute('class', 'code');
setText(e, code);
report.appendChild(e);
}
function reportFailure(code, expected, actual) {
var report, e;
report = document.getElementById('report');
e = document.createElement('p');
setText(e, 'Code:');
report.appendChild(e);
e = document.createElement('pre');
e.setAttribute('class', 'code');
setText(e, code);
report.appendChild(e);
e = document.createElement('p');
setText(e, 'Expected');
report.appendChild(e);
e = document.createElement('pre');
e.setAttribute('class', 'expected');
setText(e, expected);
report.appendChild(e);
e = document.createElement('p');
setText(e, 'Actual');
report.appendChild(e);
e = document.createElement('pre');
e.setAttribute('class', 'actual');
setText(e, actual);
report.appendChild(e);
}
setText(document.getElementById('version'), esprima.version);
tick = new Date();
for (category in testFixture) {
if (testFixture.hasOwnProperty(category)) {
startCategory(category);
fixture = testFixture[category];
for (source in fixture) {
if (fixture.hasOwnProperty(source)) {
expected = fixture[source];
total += 1;
try {
runTest(esprima, source, expected);
reportSuccess(source, JSON.stringify(expected, null, 4));
} catch (e) {
failures += 1;
reportFailure(source, e.expected, e.actual);
}
}
}
}
}
tick = (new Date()) - tick;
if (failures > 0) {
document.getElementById('status').className = 'alert-box alert';
setText(document.getElementById('status'), total + ' tests. ' +
'Failures: ' + failures + '. ' + tick + ' ms.');
} else {
document.getElementById('status').className = 'alert-box success';
setText(document.getElementById('status'), total + ' tests. ' +
'No failure. ' + tick + ' ms.');
}
};
} else {
(function () {
'use strict';
var esprima = require('../esprima'),
vm = require('vm'),
fs = require('fs'),
diff = require('json-diff').diffString,
total = 0,
failures = [],
tick = new Date(),
expected,
header;
vm.runInThisContext(fs.readFileSync(__dirname + '/test.js', 'utf-8'));
Object.keys(testFixture).forEach(function (category) {
Object.keys(testFixture[category]).forEach(function (source) {
total += 1;
expected = testFixture[category][source];
try {
runTest(esprima, source, expected);
} catch (e) {
e.source = source;
failures.push(e);
}
});
});
tick = (new Date()) - tick;
header = total + ' tests. ' + failures.length + ' failures. ' +
tick + ' ms';
if (failures.length) {
console.error(header);
failures.forEach(function (failure) {
try {
var expectedObject = JSON.parse(failure.expected);
var actualObject = JSON.parse(failure.actual);
console.error(failure.source + ': Expected\n ' +
failure.expected.split('\n').join('\n ') +
'\nto match\n ' + failure.actual + '\nDiff:\n' +
diff(expectedObject, actualObject));
} catch (ex) {
console.error(failure.source + ': Expected\n ' +
failure.expected.split('\n').join('\n ') +
'\nto match\n ' + failure.actual);
}
});
} else {
console.log(header);
}
process.exit(failures.length === 0 ? 0 : 1);
}());
}

File diff suppressed because it is too large Load Diff

45
frontend/node_modules/jsonpath/package.json generated vendored Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "jsonpath",
"description": "Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.",
"version": "1.1.1",
"author": "david@fmail.co.uk",
"scripts": {
"prepublishOnly": "node lib/aesprim.js > generated/aesprim-browser.js",
"test": "mocha -u tdd test && jscs lib && jshint lib",
"generate": "node bin/generate_parser.js > generated/parser.js"
},
"dependencies": {
"esprima": "1.2.2",
"static-eval": "2.0.2",
"underscore": "1.12.1"
},
"browser": "./jsonpath.js",
"alias": {
"./lib/aesprim.js": "./generated/aesprim-browser.js"
},
"devDependencies": {
"grunt": "0.4.5",
"grunt-browserify": "3.8.0",
"grunt-cli": "0.1.13",
"grunt-contrib-uglify": "0.9.1",
"jison": "0.4.13",
"jscs": "1.10.0",
"jshint": "2.6.0",
"mocha": "2.1.0"
},
"repository": {
"type": "git",
"url": "https://github.com/dchester/jsonpath"
},
"keywords": [
"JSONPath",
"jsonpath",
"json-path",
"object",
"traversal",
"json",
"path",
"data structures"
],
"license": "MIT"
}

31
frontend/node_modules/jsonpath/test/data/store.json generated vendored Normal file
View File

@@ -0,0 +1,31 @@
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}

38
frontend/node_modules/jsonpath/test/lessons.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
var assert = require('assert');
var jp = require('../');
var data = require('./data/store.json');
suite('orig-google-code-issues', function() {
test('comma in eval', function() {
var pathExpression = '$..book[?(@.price && ",")]'
var results = jp.query(data, pathExpression);
assert.deepEqual(results, data.store.book);
});
test('member names with dots', function() {
var data = { 'www.google.com': 42, 'www.wikipedia.org': 190 };
var results = jp.query(data, "$['www.google.com']");
assert.deepEqual(results, [ 42 ]);
});
test('nested objects with filter', function() {
var data = { dataResult: { object: { objectInfo: { className: "folder", typeName: "Standard Folder", id: "uniqueId" } } } };
var results = jp.query(data, "$..object[?(@.className=='folder')]");
assert.deepEqual(results, [ data.dataResult.object.objectInfo ]);
});
test('script expressions with @ char', function() {
var data = { "DIV": [{ "@class": "value", "val": 5 }] };
var results = jp.query(data, "$..DIV[?(@['@class']=='value')]");
assert.deepEqual(results, data.DIV);
});
test('negative slices', function() {
var results = jp.query(data, "$..book[-1:].title");
assert.deepEqual(results, ['The Lord of the Rings']);
});
});

164
frontend/node_modules/jsonpath/test/parse.js generated vendored Normal file
View File

@@ -0,0 +1,164 @@
var assert = require('assert');
var jp = require('../');
var util = require('util');
suite('parse', function() {
test('should parse root-only', function() {
var path = jp.parse('$');
assert.deepEqual(path, [ { expression: { type: 'root', value: '$' } } ]);
});
test('parse path for store', function() {
var path = jp.parse('$.store');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } }
])
});
test('parse path for the authors of all books in the store', function() {
var path = jp.parse('$.store.book[*].author');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'wildcard', value: '*' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'author' } }
])
});
test('parse path for all authors', function() {
var path = jp.parse('$..author');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'author' } }
])
});
test('parse path for all authors via subscript descendant string literal', function() {
var path = jp.parse("$..['author']");
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'subscript', scope: 'descendant', expression: { type: 'string_literal', value: 'author' } }
])
});
test('parse path for all things in store', function() {
var path = jp.parse('$.store.*');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
{ operation: 'member', scope: 'child', expression: { type: 'wildcard', value: '*' } }
])
});
test('parse path for price of everything in the store', function() {
var path = jp.parse('$.store..price');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'price' } }
])
});
test('parse path for the last book in order via expression', function() {
var path = jp.parse('$..book[(@.length-1)]');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'script_expression', value: '(@.length-1)' } }
])
});
test('parse path for the first two books via union', function() {
var path = jp.parse('$..book[0,1]');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'union', value: [ { expression: { type: 'numeric_literal', value: '0' } }, { expression: { type: 'numeric_literal', value: '1' } } ] } }
])
});
test('parse path for the first two books via slice', function() {
var path = jp.parse('$..book[0:2]');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'slice', value: '0:2' } }
])
});
test('parse path to filter all books with isbn number', function() {
var path = jp.parse('$..book[?(@.isbn)]');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'filter_expression', value: '?(@.isbn)' } }
])
});
test('parse path to filter all books with a price less than 10', function() {
var path = jp.parse('$..book[?(@.price<10)]');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
{ operation: 'subscript', scope: 'child', expression: { type: 'filter_expression', value: '?(@.price<10)' } }
])
});
test('parse path to match all elements', function() {
var path = jp.parse('$..*');
assert.deepEqual(path, [
{ expression: { type: 'root', value: '$' } },
{ operation: 'member', scope: 'descendant', expression: { type: 'wildcard', value: '*' } }
])
});
test('parse path with leading member', function() {
var path = jp.parse('store');
assert.deepEqual(path, [
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } }
])
});
test('parse path with leading member and followers', function() {
var path = jp.parse('Request.prototype.end');
assert.deepEqual(path, [
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'Request' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'prototype' } },
{ operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'end' } }
])
});
test('parser ast is reinitialized after parse() throws', function() {
assert.throws(function() { var path = jp.parse('store.book...') })
var path = jp.parse('$..price');
assert.deepEqual(path, [
{ "expression": { "type": "root", "value": "$" } },
{ "expression": { "type": "identifier", "value": "price" }, "operation": "member", "scope": "descendant"}
])
});
});
suite('parse-negative', function() {
test('parse path with leading member component throws', function() {
assert.throws(function(e) { var path = jp.parse('.store') }, /Expecting 'DOLLAR'/)
});
test('parse path with leading descendant member throws', function() {
assert.throws(function() { var path = jp.parse('..store') }, /Expecting 'DOLLAR'/)
});
test('leading script throws', function() {
assert.throws(function() { var path = jp.parse('()') }, /Unrecognized text/)
});
test('first time friendly error', function() {
assert.throws(function() { (new jp.JSONPath).parse('$...') }, /Expecting 'STAR'/)
});
});

359
frontend/node_modules/jsonpath/test/query.js generated vendored Normal file
View File

@@ -0,0 +1,359 @@
var assert = require('assert');
var jp = require('../');
var data = require('./data/store.json');
suite('query', function() {
test('first-level member', function() {
var results = jp.nodes(data, '$.store');
assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store } ]);
});
test('authors of all books in the store', function() {
var results = jp.nodes(data, '$.store.book[*].author');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
{ path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
{ path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
{ path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
]);
});
test('all authors', function() {
var results = jp.nodes(data, '$..author');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
{ path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
{ path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
{ path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
]);
});
test('all authors via subscript descendant string literal', function() {
var results = jp.nodes(data, "$..['author']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
{ path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
{ path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
{ path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
]);
});
test('all things in store', function() {
var results = jp.nodes(data, '$.store.*');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book'], value: data.store.book },
{ path: ['$', 'store', 'bicycle'], value: data.store.bicycle }
]);
});
test('price of everything in the store', function() {
var results = jp.nodes(data, '$.store..price');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'price'], value: 8.95 },
{ path: ['$', 'store', 'book', 1, 'price'], value: 12.99 },
{ path: ['$', 'store', 'book', 2, 'price'], value: 8.99 },
{ path: ['$', 'store', 'book', 3, 'price'], value: 22.99 },
{ path: ['$', 'store', 'bicycle', 'price'], value: 19.95 }
]);
});
test('last book in order via expression', function() {
var results = jp.nodes(data, '$..book[(@.length-1)]');
assert.deepEqual(results, [ { path: ['$', 'store', 'book', 3], value: data.store.book[3] }]);
});
test('first two books via union', function() {
var results = jp.nodes(data, '$..book[0,1]');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0], value: data.store.book[0] },
{ path: ['$', 'store', 'book', 1], value: data.store.book[1] }
]);
});
test('first two books via slice', function() {
var results = jp.nodes(data, '$..book[0:2]');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0], value: data.store.book[0] },
{ path: ['$', 'store', 'book', 1], value: data.store.book[1] }
]);
});
test('filter all books with isbn number', function() {
var results = jp.nodes(data, '$..book[?(@.isbn)]');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 2], value: data.store.book[2] },
{ path: ['$', 'store', 'book', 3], value: data.store.book[3] }
]);
});
test('filter all books with a price less than 10', function() {
var results = jp.nodes(data, '$..book[?(@.price<10)]');
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0], value: data.store.book[0] },
{ path: ['$', 'store', 'book', 2], value: data.store.book[2] }
]);
});
test('first ten of all elements', function() {
var results = jp.nodes(data, '$..*', 10);
assert.deepEqual(results, [
{ path: [ '$', 'store' ], value: data.store },
{ path: [ '$', 'store', 'book' ], value: data.store.book },
{ path: [ '$', 'store', 'bicycle' ], value: data.store.bicycle },
{ path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] },
{ path: [ '$', 'store', 'book', 1 ], value: data.store.book[1] },
{ path: [ '$', 'store', 'book', 2 ], value: data.store.book[2] },
{ path: [ '$', 'store', 'book', 3 ], value: data.store.book[3] },
{ path: [ '$', 'store', 'book', 0, 'category' ], value: 'reference' },
{ path: [ '$', 'store', 'book', 0, 'author' ], value: 'Nigel Rees' },
{ path: [ '$', 'store', 'book', 0, 'title' ], value: 'Sayings of the Century' }
])
});
test('all elements', function() {
var results = jp.nodes(data, '$..*');
assert.deepEqual(results, [
{ path: [ '$', 'store' ], value: data.store },
{ path: [ '$', 'store', 'book' ], value: data.store.book },
{ path: [ '$', 'store', 'bicycle' ], value: data.store.bicycle },
{ path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] },
{ path: [ '$', 'store', 'book', 1 ], value: data.store.book[1] },
{ path: [ '$', 'store', 'book', 2 ], value: data.store.book[2] },
{ path: [ '$', 'store', 'book', 3 ], value: data.store.book[3] },
{ path: [ '$', 'store', 'book', 0, 'category' ], value: 'reference' },
{ path: [ '$', 'store', 'book', 0, 'author' ], value: 'Nigel Rees' },
{ path: [ '$', 'store', 'book', 0, 'title' ], value: 'Sayings of the Century' },
{ path: [ '$', 'store', 'book', 0, 'price' ], value: 8.95 },
{ path: [ '$', 'store', 'book', 1, 'category' ], value: 'fiction' },
{ path: [ '$', 'store', 'book', 1, 'author' ], value: 'Evelyn Waugh' },
{ path: [ '$', 'store', 'book', 1, 'title' ], value: 'Sword of Honour' },
{ path: [ '$', 'store', 'book', 1, 'price' ], value: 12.99 },
{ path: [ '$', 'store', 'book', 2, 'category' ], value: 'fiction' },
{ path: [ '$', 'store', 'book', 2, 'author' ], value: 'Herman Melville' },
{ path: [ '$', 'store', 'book', 2, 'title' ], value: 'Moby Dick' },
{ path: [ '$', 'store', 'book', 2, 'isbn' ], value: '0-553-21311-3' },
{ path: [ '$', 'store', 'book', 2, 'price' ], value: 8.99 },
{ path: [ '$', 'store', 'book', 3, 'category' ], value: 'fiction' },
{ path: [ '$', 'store', 'book', 3, 'author' ], value: 'J. R. R. Tolkien' },
{ path: [ '$', 'store', 'book', 3, 'title' ], value: 'The Lord of the Rings' },
{ path: [ '$', 'store', 'book', 3, 'isbn' ], value: '0-395-19395-8' },
{ path: [ '$', 'store', 'book', 3, 'price' ], value: 22.99 },
{ path: [ '$', 'store', 'bicycle', 'color' ], value: 'red' },
{ path: [ '$', 'store', 'bicycle', 'price' ], value: 19.95 }
]);
});
test('all elements via subscript wildcard', function() {
var results = jp.nodes(data, '$..*');
assert.deepEqual(jp.nodes(data, '$..[*]'), jp.nodes(data, '$..*'));
});
test('object subscript wildcard', function() {
var results = jp.query(data, '$.store[*]');
assert.deepEqual(results, [ data.store.book, data.store.bicycle ]);
});
test('no match returns empty array', function() {
var results = jp.nodes(data, '$..bookz');
assert.deepEqual(results, []);
});
test('member numeric literal gets first element', function() {
var results = jp.nodes(data, '$.store.book.0');
assert.deepEqual(results, [ { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] } ]);
});
test('member numeric literal matches string-numeric key', function() {
var data = { authors: { '1': 'Herman Melville', '2': 'J. R. R. Tolkien' } };
var results = jp.nodes(data, '$.authors.1');
assert.deepEqual(results, [ { path: [ '$', 'authors', 1 ], value: 'Herman Melville' } ]);
});
test('descendant numeric literal gets first element', function() {
var results = jp.nodes(data, '$.store.book..0');
assert.deepEqual(results, [ { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] } ]);
});
test('root element gets us original obj', function() {
var results = jp.nodes(data, '$');
assert.deepEqual(results, [ { path: ['$'], value: data } ]);
});
test('subscript double-quoted string', function() {
var results = jp.nodes(data, '$["store"]');
assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
});
test('subscript single-quoted string', function() {
var results = jp.nodes(data, "$['store']");
assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
});
test('leading member component', function() {
var results = jp.nodes(data, "store");
assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
});
test('union of three array slices', function() {
var results = jp.query(data, "$.store.book[0:1,1:2,2:3]");
assert.deepEqual(results, data.store.book.slice(0,3));
});
test('slice with step > 1', function() {
var results = jp.query(data, "$.store.book[0:4:2]");
assert.deepEqual(results, [ data.store.book[0], data.store.book[2]]);
});
test('union of subscript string literal keys', function() {
var results = jp.nodes(data, "$.store['book','bicycle']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book'], value: data.store.book },
{ path: ['$', 'store', 'bicycle'], value: data.store.bicycle },
]);
});
test('union of subscript string literal three keys', function() {
var results = jp.nodes(data, "$.store.book[0]['title','author','price']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price }
]);
});
test('union of subscript integer three keys followed by member-child-identifier', function() {
var results = jp.nodes(data, "$.store.book[1,2,3]['title']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title }
]);
});
test('union of subscript integer three keys followed by union of subscript string literal three keys', function() {
var results = jp.nodes(data, "$.store.book[0,1,2,3]['title','author','price']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
]);
});
test('union of subscript integer four keys, including an inexistent one, followed by union of subscript string literal three keys', function() {
var results = jp.nodes(data, "$.store.book[0,1,2,3,151]['title','author','price']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
]);
});
test('union of subscript integer three keys followed by union of subscript string literal three keys, followed by inexistent literal key', function() {
var results = jp.nodes(data, "$.store.book[0,1,2,3]['title','author','price','fruit']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
]);
});
test('union of subscript 4 array slices followed by union of subscript string literal three keys', function() {
var results = jp.nodes(data, "$.store.book[0:1,1:2,2:3,3:4]['title','author','price']");
assert.deepEqual(results, [
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
]);
});
test('nested parentheses eval', function() {
var pathExpression = '$..book[?( @.price && (@.price + 20 || false) )]'
var results = jp.query(data, pathExpression);
assert.deepEqual(results, data.store.book);
});
test('array indexes from 0 to 100', function() {
var data = [];
for (var i = 0; i <= 100; ++i)
data[i] = Math.random();
for (var i = 0; i <= 100; ++i) {
var results = jp.query(data, '$[' + i.toString() + ']');
assert.deepEqual(results, [data[i]]);
}
});
test('descendant subscript numeric literal', function() {
var data = [ 0, [ 1, 2, 3 ], [ 4, 5, 6 ] ];
var results = jp.query(data, '$..[0]');
assert.deepEqual(results, [ 0, 1, 4 ]);
});
test('descendant subscript numeric literal', function() {
var data = [ 0, 1, [ 2, 3, 4 ], [ 5, 6, 7, [ 8, 9 , 10 ] ] ];
var results = jp.query(data, '$..[0,1]');
assert.deepEqual(results, [ 0, 1, 2, 3, 5, 6, 8, 9 ]);
});
test('throws for no input', function() {
assert.throws(function() { jp.query() }, /needs to be an object/);
});
test('throws for bad input', function() {
assert.throws(function() { jp.query("string", "string") }, /needs to be an object/);
});
test('throws for bad input', function() {
assert.throws(function() { jp.query({}, null) }, /we need a path/);
});
test('throws for bad input', function() {
assert.throws(function() { jp.query({}, 42) }, /we need a path/);
});
test('union on objects', function() {
assert.deepEqual(jp.query({a: 1, b: 2, c: null}, '$..["a","b","c","d"]'), [1, 2, null]);
});
});

57
frontend/node_modules/jsonpath/test/slice.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
var assert = require('assert');
var slice = require('../lib/slice');
var data = ['a', 'b', 'c', 'd', 'e', 'f'];
suite('slice', function() {
test('no params yields copy', function() {
assert.deepEqual(slice(data), data);
});
test('no end param defaults to end', function() {
assert.deepEqual(slice(data, 2), data.slice(2));
});
test('zero end param yields empty', function() {
assert.deepEqual(slice(data, 0, 0), []);
});
test('first element with explicit params', function() {
assert.deepEqual(slice(data, 0, 1, 1), ['a']);
});
test('last element with explicit params', function() {
assert.deepEqual(slice(data, -1, 6), ['f']);
});
test('empty extents and negative step reverses', function() {
assert.deepEqual(slice(data, null, null, -1), ['f', 'e', 'd', 'c', 'b', 'a']);
});
test('negative step partial slice', function() {
assert.deepEqual(slice(data, 4, 2, -1), ['e', 'd']);
});
test('negative step partial slice no start defaults to end', function() {
assert.deepEqual(slice(data, null, 2, -1), ['f', 'e', 'd']);
});
test('extents clamped end', function() {
assert.deepEqual(slice(data, null, 100), data);
});
test('extents clamped beginning', function() {
assert.deepEqual(slice(data, -100, 100), data);
});
test('backwards extents yields empty', function() {
assert.deepEqual(slice(data, 2, 1), []);
});
test('zero step gets shot down', function() {
assert.throws(function() { slice(data, null, null, 0) });
});
});

54
frontend/node_modules/jsonpath/test/stringify.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
var assert = require('assert');
var jp = require('../');
suite('stringify', function() {
test('simple path stringifies', function() {
var string = jp.stringify(['$', 'a', 'b', 'c']);
assert.equal(string, '$.a.b.c');
});
test('numeric literals end up as subscript numbers', function() {
var string = jp.stringify(['$', 'store', 'book', 0, 'author']);
assert.equal(string, '$.store.book[0].author');
});
test('simple path with no leading root stringifies', function() {
var string = jp.stringify(['a', 'b', 'c']);
assert.equal(string, '$.a.b.c');
});
test('simple parsed path stringifies', function() {
var path = [
{ scope: 'child', operation: 'member', expression: { type: 'identifier', value: 'a' } },
{ scope: 'child', operation: 'member', expression: { type: 'identifier', value: 'b' } },
{ scope: 'child', operation: 'member', expression: { type: 'identifier', value: 'c' } }
];
var string = jp.stringify(path);
assert.equal(string, '$.a.b.c');
});
test('keys with hyphens get subscripted', function() {
var string = jp.stringify(['$', 'member-search']);
assert.equal(string, '$["member-search"]');
});
test('complicated path round trips', function() {
var pathExpression = '$..*[0:2].member["string-xyz"]';
var path = jp.parse(pathExpression);
var string = jp.stringify(path);
assert.equal(string, pathExpression);
});
test('complicated path with filter exp round trips', function() {
var pathExpression = '$..*[0:2].member[?(@.val > 10)]';
var path = jp.parse(pathExpression);
var string = jp.stringify(path);
assert.equal(string, pathExpression);
});
test('throws for no input', function() {
assert.throws(function() { jp.stringify() }, /we need a path/);
});
});

72
frontend/node_modules/jsonpath/test/sugar.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
var assert = require('assert');
var jp = require('../');
var util = require('util');
suite('sugar', function() {
test('parent gets us parent value', function() {
var data = { a: 1, b: 2, c: 3, z: { a: 100, b: 200 } };
var parent = jp.parent(data, '$.z.b');
assert.equal(parent, data.z);
});
test('apply method sets values', function() {
var data = { a: 1, b: 2, c: 3, z: { a: 100, b: 200 } };
jp.apply(data, '$..a', function(v) { return v + 1 });
assert.equal(data.a, 2);
assert.equal(data.z.a, 101);
});
test('apply method applies survives structural changes', function() {
var data = {a: {b: [1, {c: [2,3]}]}};
jp.apply(data, '$..*[?(@.length > 1)]', function(array) {
return array.reverse();
});
assert.deepEqual(data.a.b, [{c: [3, 2]}, 1]);
});
test('value method gets us a value', function() {
var data = { a: 1, b: 2, c: 3, z: { a: 100, b: 200 } };
var b = jp.value(data, '$..b')
assert.equal(b, data.b);
});
test('value method sets us a value', function() {
var data = { a: 1, b: 2, c: 3, z: { a: 100, b: 200 } };
var b = jp.value(data, '$..b', '5000')
assert.equal(b, 5000);
assert.equal(data.b, 5000);
});
test('value method sets new key and value', function() {
var data = {};
var a = jp.value(data, '$.a', 1);
var c = jp.value(data, '$.b.c', 2);
assert.equal(a, 1);
assert.equal(data.a, 1);
assert.equal(c, 2);
assert.equal(data.b.c, 2);
});
test('value method sets new array value', function() {
var data = {};
var v1 = jp.value(data, '$.a.d[0]', 4);
var v2 = jp.value(data, '$.a.d[1]', 5);
assert.equal(v1, 4);
assert.equal(v2, 5);
assert.deepEqual(data.a.d, [4, 5]);
});
test('value method sets non-literal key', function() {
var data = { "list": [ { "index": 0, "value": "default" }, { "index": 1, "value": "default" } ] };
jp.value(data, '$.list[?(@.index == 1)].value', "test");
assert.equal(data.list[1].value, "test");
});
test('paths with a count gets us back count many paths', function() {
data = [ { a: [ 1, 2, 3 ], b: [ -1, -2, -3 ] }, { } ]
paths = jp.paths(data, '$..*', 3)
assert.deepEqual(paths, [ ['$', '0'], ['$', '1'], ['$', '0', 'a'] ]);
});
});