mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-02-22 14:00:03 +00:00
Replace pegs parser with Esprima
It preserves comments and text positions, enabling us to do syntax highlighting. Hopefully.
This commit is contained in:
parent
470b622bb1
commit
f6338d9109
@ -34,6 +34,8 @@ var App = function() {
|
|||||||
this.store.registerParser("image/jpeg",imageParser);
|
this.store.registerParser("image/jpeg",imageParser);
|
||||||
this.store.registerParser("image/png",imageParser);
|
this.store.registerParser("image/png",imageParser);
|
||||||
this.store.registerParser("image/gif",imageParser);
|
this.store.registerParser("image/gif",imageParser);
|
||||||
|
// Set up the JavaScript parser
|
||||||
|
this.store.jsParser = new JavaScriptParser();
|
||||||
// Register the standard tiddler serializers and deserializers
|
// Register the standard tiddler serializers and deserializers
|
||||||
tiddlerInput.register(this.store);
|
tiddlerInput.register(this.store);
|
||||||
tiddlerOutput.register(this.store);
|
tiddlerOutput.register(this.store);
|
||||||
@ -79,12 +81,6 @@ var App = function() {
|
|||||||
this.store.addTiddler(new Tiddler(tiddlers[t]));
|
this.store.addTiddler(new Tiddler(tiddlers[t]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set up the JavaScript parser. Currently a hack; the idea is that the parsers would be loaded through a boot recipe
|
|
||||||
if(this.isBrowser) {
|
|
||||||
this.store.jsParser = new JavaScriptParser(this.store.getTiddlerText("javascript.pegjs"));
|
|
||||||
} else {
|
|
||||||
this.store.jsParser = new JavaScriptParser(require("fs").readFileSync("parsers/javascript.pegjs","utf8"));
|
|
||||||
}
|
|
||||||
// Bit of a hack to set up the macros
|
// Bit of a hack to set up the macros
|
||||||
this.store.installMacro(require("./macros/echo.js").macro);
|
this.store.installMacro(require("./macros/echo.js").macro);
|
||||||
this.store.installMacro(require("./macros/image.js").macro);
|
this.store.installMacro(require("./macros/image.js").macro);
|
||||||
|
@ -18,7 +18,8 @@ This simplifies coalescing adjacent constants into a single string.
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("./Utils.js");
|
var esprima = require("esprima"),
|
||||||
|
utils = require("./Utils.js");
|
||||||
|
|
||||||
// Create a new JavaScript tree object
|
// Create a new JavaScript tree object
|
||||||
var JavaScriptParseTree = function(tree) {
|
var JavaScriptParseTree = function(tree) {
|
||||||
@ -42,127 +43,7 @@ JavaScriptParseTree.prototype.toString = function() {
|
|||||||
// Compile the entire JavaScript tree object to a renderer object
|
// Compile the entire JavaScript tree object to a renderer object
|
||||||
JavaScriptParseTree.prototype.compileJS = function() {
|
JavaScriptParseTree.prototype.compileJS = function() {
|
||||||
/*jslint evil: true */
|
/*jslint evil: true */
|
||||||
var output = [];
|
return {render: eval(esprima.generate(this.tree))};
|
||||||
if(this.tree instanceof Array) {
|
|
||||||
this.compileSubTree(output,this.tree);
|
|
||||||
} else {
|
|
||||||
this.compileNode(output,this.tree);
|
|
||||||
}
|
|
||||||
var r = output.join("");
|
|
||||||
return {render: eval(r)};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Compile a subtree of the parse tree to an array of fragments of JavaScript source code
|
|
||||||
JavaScriptParseTree.prototype.compileSubTree = function(output,tree) {
|
|
||||||
for(var t=0; t<tree.length; t++) {
|
|
||||||
if(t) {
|
|
||||||
this.output.push(";\n");
|
|
||||||
}
|
|
||||||
this.compileNode(output,tree[t]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Compile a JavaScript node to an array of fragments of JavaScript source code
|
|
||||||
|
|
||||||
The code currently inserts some unneeded parenthesis because it doesn't look
|
|
||||||
at the binding order of operators to determine if they are needed.
|
|
||||||
*/
|
|
||||||
JavaScriptParseTree.prototype.compileNode = function(output,node) {
|
|
||||||
var p;
|
|
||||||
switch(node.type) {
|
|
||||||
case "StringLiteral":
|
|
||||||
output.push('"' + utils.stringify(node.value) + '"');
|
|
||||||
break;
|
|
||||||
case "StringLiterals":
|
|
||||||
output.push('"' + utils.stringify(node.value.join("")) + '"');
|
|
||||||
break;
|
|
||||||
case "FunctionCall":
|
|
||||||
output.push("(");
|
|
||||||
this.compileNode(output,node.name);
|
|
||||||
output.push(")(");
|
|
||||||
for(p=0; p<node["arguments"].length; p++) {
|
|
||||||
if(p) {
|
|
||||||
output.push(",");
|
|
||||||
}
|
|
||||||
this.compileNode(output,node["arguments"][p]);
|
|
||||||
}
|
|
||||||
output.push(")");
|
|
||||||
break;
|
|
||||||
case "PropertyAccess":
|
|
||||||
this.compileNode(output,node.base);
|
|
||||||
if(typeof node.name === "string") {
|
|
||||||
output.push("." + node.name);
|
|
||||||
} else {
|
|
||||||
output.push("[");
|
|
||||||
this.compileNode(output,node.name);
|
|
||||||
output.push("]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "ArrayLiteral":
|
|
||||||
output.push("[");
|
|
||||||
for(p=0; p<node.elements.length; p++) {
|
|
||||||
if(p) {
|
|
||||||
output.push(",");
|
|
||||||
}
|
|
||||||
this.compileNode(output,node.elements[p]);
|
|
||||||
}
|
|
||||||
output.push("]");
|
|
||||||
break;
|
|
||||||
case "Variable":
|
|
||||||
output.push(node.name);
|
|
||||||
break;
|
|
||||||
case "ObjectLiteral":
|
|
||||||
output.push("{");
|
|
||||||
for(p=0; p<node.properties.length; p++) {
|
|
||||||
if(p) {
|
|
||||||
output.push(",");
|
|
||||||
}
|
|
||||||
this.compileNode(output,node.properties[p]);
|
|
||||||
}
|
|
||||||
output.push("}");
|
|
||||||
break;
|
|
||||||
case "PropertyAssignment":
|
|
||||||
output.push("'");
|
|
||||||
output.push(node.name);
|
|
||||||
output.push("':");
|
|
||||||
this.compileNode(output,node.value);
|
|
||||||
break;
|
|
||||||
case "BinaryExpression":
|
|
||||||
output.push("(");
|
|
||||||
this.compileNode(output,node.left);
|
|
||||||
output.push(")");
|
|
||||||
output.push(node.operator);
|
|
||||||
output.push("(");
|
|
||||||
this.compileNode(output,node.right);
|
|
||||||
output.push(")");
|
|
||||||
break;
|
|
||||||
case "NumericLiteral":
|
|
||||||
output.push(node.value);
|
|
||||||
break;
|
|
||||||
case "Function":
|
|
||||||
output.push("(function ");
|
|
||||||
if(node.name !== null) {
|
|
||||||
output.push(node.name);
|
|
||||||
}
|
|
||||||
output.push("(");
|
|
||||||
output.push(node.params.join(","));
|
|
||||||
output.push("){");
|
|
||||||
this.compileSubTree(output,node.elements);
|
|
||||||
output.push("})");
|
|
||||||
break;
|
|
||||||
case "ReturnStatement":
|
|
||||||
output.push("return ");
|
|
||||||
this.compileNode(output,node.value);
|
|
||||||
break;
|
|
||||||
case "This":
|
|
||||||
output.push("this");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(node);
|
|
||||||
throw "Unknown JavaScript node type: " + node.type;
|
|
||||||
//break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.JavaScriptParseTree = JavaScriptParseTree;
|
exports.JavaScriptParseTree = JavaScriptParseTree;
|
||||||
|
@ -10,16 +10,15 @@ Parses JavaScript source code into a parse tree using PEGJS
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var JavaScriptParseTree = require("./JavaScriptParseTree.js").JavaScriptParseTree,
|
var JavaScriptParseTree = require("./JavaScriptParseTree.js").JavaScriptParseTree,
|
||||||
pegjs = require("pegjs");
|
esprima = require("esprima");
|
||||||
|
|
||||||
// Initialise the parser
|
// Initialise the parser
|
||||||
var JavaScriptParser = function(parserText) {
|
var JavaScriptParser = function() {
|
||||||
this.parser = pegjs.buildParser(parserText);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse a string of JavaScript code and return the parse tree
|
// Parse a string of JavaScript code and return the parse tree
|
||||||
JavaScriptParser.prototype.parse = function(code) {
|
JavaScriptParser.prototype.parse = function(code) {
|
||||||
return new JavaScriptParseTree(this.parser.parse(code),this);
|
return new JavaScriptParseTree(esprima.parse(code));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a parse tree object from a raw tree
|
// Create a parse tree object from a raw tree
|
||||||
|
@ -84,17 +84,43 @@ MacroNode.prototype.parseMacroParamString = function(paramString) {
|
|||||||
self = this,
|
self = this,
|
||||||
insertParam = function(name,arg) {
|
insertParam = function(name,arg) {
|
||||||
if(arg.evaluated) {
|
if(arg.evaluated) {
|
||||||
params[name] = self.store.jsParser.createTree([
|
params[name] = self.store.jsParser.createTree( // (function(tiddler,store,utils) {return {paramOne: 1};})
|
||||||
{
|
{
|
||||||
type: "Function",
|
"type": "Program",
|
||||||
name: null,
|
"body": [
|
||||||
params: ["tiddler","store","utils"], // These are the parameters passed to the parameter expressions
|
{
|
||||||
elements: [ {
|
"type": "ExpressionStatement",
|
||||||
type: "ReturnStatement",
|
"expression": {
|
||||||
value: self.store.jsParser.parse(arg.string).tree.elements[0]
|
"type": "FunctionExpression",
|
||||||
} ]
|
"id": null,
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"name": "tiddler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"name": "store"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"name": "utils"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ReturnStatement",
|
||||||
|
"argument": self.store.jsParser.parse("(" + arg.string + ")").tree.body[0].expression
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]).compile("application/javascript").render;
|
).compile("application/javascript").render;
|
||||||
} else {
|
} else {
|
||||||
params[name] = arg.string;
|
params[name] = arg.string;
|
||||||
}
|
}
|
||||||
@ -399,12 +425,12 @@ RawNode.prototype.renderInDom = function(domNode) {
|
|||||||
Static method to construct a label
|
Static method to construct a label
|
||||||
*/
|
*/
|
||||||
var LabelNode = function(type,value,classes) {
|
var LabelNode = function(type,value,classes) {
|
||||||
classes = (classes || []).slice(0);
|
classes = (classes || []).slice(0);
|
||||||
classes.push("label");
|
classes.push("label");
|
||||||
return new ElementNode("span",{
|
return new ElementNode("span",{
|
||||||
"class": classes,
|
"class": classes,
|
||||||
"data-tw-label-type": type
|
"data-tw-label-type": type
|
||||||
},value);
|
},value);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
1
node_modules/.bin/esparse
generated
vendored
Symbolic link
1
node_modules/.bin/esparse
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../esprima/bin/esparse.js
|
1
node_modules/.bin/pegjs
generated
vendored
1
node_modules/.bin/pegjs
generated
vendored
@ -1 +0,0 @@
|
|||||||
../pegjs/bin/pegjs
|
|
5
node_modules/esprima/.travis.yml
generated
vendored
Normal file
5
node_modules/esprima/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 0.4
|
||||||
|
- 0.6
|
||||||
|
|
19
node_modules/esprima/LICENSE.BSD
generated
vendored
Normal file
19
node_modules/esprima/LICENSE.BSD
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
66
node_modules/esprima/README.md
generated
vendored
Normal file
66
node_modules/esprima/README.md
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
Esprima ([esprima.org](http://esprima.org)) is an educational
|
||||||
|
[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
||||||
|
(also popularly known as [JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript))
|
||||||
|
parsing infrastructure for multipurpose analysis. It is also written in ECMAScript.
|
||||||
|
|
||||||
|
Esprima can be used in a web browser:
|
||||||
|
|
||||||
|
<script src="esprima.js"></script>
|
||||||
|
|
||||||
|
or in a Node.js application via the package manager:
|
||||||
|
|
||||||
|
npm install esprima
|
||||||
|
|
||||||
|
Esprima parser output is compatible with Mozilla (SpiderMonkey)
|
||||||
|
[Parser API](https://developer.mozilla.org/en/SpiderMonkey/Parser_API).
|
||||||
|
|
||||||
|
A very simple example:
|
||||||
|
|
||||||
|
esprima.parse('var answer=42').body[0].declarations[0].init
|
||||||
|
|
||||||
|
produces the following object:
|
||||||
|
|
||||||
|
{ type: 'Literal', value: 42 }
|
||||||
|
|
||||||
|
Esprima is still in the development, for now please check
|
||||||
|
[the wiki documentation](http://wiki.esprima.org).
|
||||||
|
|
||||||
|
Since it is not comprehensive nor complete, refer to the
|
||||||
|
[issue tracker](http://issues.esprima.org) for
|
||||||
|
[known problems](http://code.google.com/p/esprima/issues/list?q=Defect)
|
||||||
|
and [future plans](http://code.google.com/p/esprima/issues/list?q=Enhancement).
|
||||||
|
Esprima is supported on [many browsers](http://code.google.com/p/esprima/wiki/BrowserCompatibility):
|
||||||
|
IE 6+, Firefox 1+, Safari 3+, Chrome 1+, and Opera 8+.
|
||||||
|
|
||||||
|
Feedback and contribution are welcomed! Please join the
|
||||||
|
[mailing list](http://groups.google.com/group/esprima) and read the
|
||||||
|
[contribution guide](http://code.google.com/p/esprima/wiki/ContributionGuide)
|
||||||
|
for further info.
|
||||||
|
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
Copyright (C) 2012, 2011 [Ariya Hidayat](http://ariya.ofilabs.com/about)
|
||||||
|
(twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)) and other contributors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
107
node_modules/esprima/assets/codemirror/codemirror.css
generated
vendored
Normal file
107
node_modules/esprima/assets/codemirror/codemirror.css
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
.CodeMirror {
|
||||||
|
line-height: 1em;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
overflow: auto;
|
||||||
|
height: 300px;
|
||||||
|
/* This is needed to prevent an IE[67] bug where the scrolled content
|
||||||
|
is visible outside of the scrolling box. */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
position: absolute; left: 0; top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
border-right: 1px solid #eee;
|
||||||
|
min-width: 2em;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-text {
|
||||||
|
color: #aaa;
|
||||||
|
text-align: right;
|
||||||
|
padding: .4em .2em .4em .4em;
|
||||||
|
white-space: pre !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: .4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror pre {
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-o-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
border-width: 0; margin: 0; padding: 0; background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 0; margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-wrap pre {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap .CodeMirror-scroll {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror textarea {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror pre.CodeMirror-cursor {
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
border-left: 1px solid black;
|
||||||
|
}
|
||||||
|
.CodeMirror-focused pre.CodeMirror-cursor {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.CodeMirror-selected { background: #d9d9d9; }
|
||||||
|
.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }
|
||||||
|
|
||||||
|
.CodeMirror-searching {
|
||||||
|
background: #ffa;
|
||||||
|
background: rgba(255, 255, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default theme */
|
||||||
|
|
||||||
|
.cm-s-default span.cm-keyword {color: #708;}
|
||||||
|
.cm-s-default span.cm-atom {color: #219;}
|
||||||
|
.cm-s-default span.cm-number {color: #164;}
|
||||||
|
.cm-s-default span.cm-def {color: #00f;}
|
||||||
|
.cm-s-default span.cm-variable {color: black;}
|
||||||
|
.cm-s-default span.cm-variable-2 {color: #05a;}
|
||||||
|
.cm-s-default span.cm-variable-3 {color: #085;}
|
||||||
|
.cm-s-default span.cm-property {color: black;}
|
||||||
|
.cm-s-default span.cm-operator {color: black;}
|
||||||
|
.cm-s-default span.cm-comment {color: #a50;}
|
||||||
|
.cm-s-default span.cm-string {color: #a11;}
|
||||||
|
.cm-s-default span.cm-string-2 {color: #f50;}
|
||||||
|
.cm-s-default span.cm-meta {color: #555;}
|
||||||
|
.cm-s-default span.cm-error {color: #f00;}
|
||||||
|
.cm-s-default span.cm-qualifier {color: #555;}
|
||||||
|
.cm-s-default span.cm-builtin {color: #30a;}
|
||||||
|
.cm-s-default span.cm-bracket {color: #cc7;}
|
||||||
|
.cm-s-default span.cm-tag {color: #170;}
|
||||||
|
.cm-s-default span.cm-attribute {color: #00c;}
|
||||||
|
.cm-s-default span.cm-header {color: #a0a;}
|
||||||
|
.cm-s-default span.cm-quote {color: #090;}
|
||||||
|
.cm-s-default span.cm-hr {color: #999;}
|
||||||
|
.cm-s-default span.cm-link {color: #00c;}
|
||||||
|
|
||||||
|
span.cm-header, span.cm-strong {font-weight: bold;}
|
||||||
|
span.cm-em {font-style: italic;}
|
||||||
|
span.cm-emstrong {font-style: italic; font-weight: bold;}
|
||||||
|
span.cm-link {text-decoration: underline;}
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
2817
node_modules/esprima/assets/codemirror/codemirror.js
generated
vendored
Normal file
2817
node_modules/esprima/assets/codemirror/codemirror.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
360
node_modules/esprima/assets/codemirror/javascript.js
generated
vendored
Normal file
360
node_modules/esprima/assets/codemirror/javascript.js
generated
vendored
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
|
var indentUnit = config.indentUnit;
|
||||||
|
var jsonMode = parserConfig.json;
|
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
var keywords = function(){
|
||||||
|
function kw(type) {return {type: type, style: "keyword"};}
|
||||||
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
||||||
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||||
|
return {
|
||||||
|
"if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||||
|
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
|
||||||
|
"var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||||
|
"function": kw("function"), "catch": kw("catch"),
|
||||||
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||||
|
"in": operator, "typeof": operator, "instanceof": operator,
|
||||||
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
var isOperatorChar = /[+\-*&%=<>!?|]/;
|
||||||
|
|
||||||
|
function chain(stream, state, f) {
|
||||||
|
state.tokenize = f;
|
||||||
|
return f(stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextUntilUnescaped(stream, end) {
|
||||||
|
var escaped = false, next;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (next == end && !escaped)
|
||||||
|
return false;
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used as scratch variables to communicate multiple values without
|
||||||
|
// consing up tons of objects.
|
||||||
|
var type, content;
|
||||||
|
function ret(tp, style, cont) {
|
||||||
|
type = tp; content = cont;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsTokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == '"' || ch == "'")
|
||||||
|
return chain(stream, state, jsTokenString(ch));
|
||||||
|
else if (/[\[\]{}\(\),;\:\.]/.test(ch))
|
||||||
|
return ret(ch);
|
||||||
|
else if (ch == "0" && stream.eat(/x/i)) {
|
||||||
|
stream.eatWhile(/[\da-f]/i);
|
||||||
|
return ret("number", "number");
|
||||||
|
}
|
||||||
|
else if (/\d/.test(ch)) {
|
||||||
|
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||||
|
return ret("number", "number");
|
||||||
|
}
|
||||||
|
else if (ch == "/") {
|
||||||
|
if (stream.eat("*")) {
|
||||||
|
return chain(stream, state, jsTokenComment);
|
||||||
|
}
|
||||||
|
else if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("comment", "comment");
|
||||||
|
}
|
||||||
|
else if (state.reAllowed) {
|
||||||
|
nextUntilUnescaped(stream, "/");
|
||||||
|
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
||||||
|
return ret("regexp", "string-2");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream.eatWhile(isOperatorChar);
|
||||||
|
return ret("operator", null, stream.current());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == "#") {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("error", "error");
|
||||||
|
}
|
||||||
|
else if (isOperatorChar.test(ch)) {
|
||||||
|
stream.eatWhile(isOperatorChar);
|
||||||
|
return ret("operator", null, stream.current());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream.eatWhile(/[\w\$_]/);
|
||||||
|
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||||
|
return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
|
||||||
|
ret("variable", "variable", word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsTokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
if (!nextUntilUnescaped(stream, quote))
|
||||||
|
state.tokenize = jsTokenBase;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsTokenComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while (ch = stream.next()) {
|
||||||
|
if (ch == "/" && maybeEnd) {
|
||||||
|
state.tokenize = jsTokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ret("comment", "comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
|
||||||
|
|
||||||
|
function JSLexical(indented, column, type, align, prev, info) {
|
||||||
|
this.indented = indented;
|
||||||
|
this.column = column;
|
||||||
|
this.type = type;
|
||||||
|
this.prev = prev;
|
||||||
|
this.info = info;
|
||||||
|
if (align != null) this.align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inScope(state, varname) {
|
||||||
|
for (var v = state.localVars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJS(state, style, type, content, stream) {
|
||||||
|
var cc = state.cc;
|
||||||
|
// Communicate our context to the combinators.
|
||||||
|
// (Less wasteful than consing up a hundred closures on every call.)
|
||||||
|
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
|
||||||
|
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = true;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||||
|
if (combinator(type, content)) {
|
||||||
|
while(cc.length && cc[cc.length - 1].lex)
|
||||||
|
cc.pop()();
|
||||||
|
if (cx.marked) return cx.marked;
|
||||||
|
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinator utils
|
||||||
|
|
||||||
|
var cx = {state: null, column: null, marked: null, cc: null};
|
||||||
|
function pass() {
|
||||||
|
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||||
|
}
|
||||||
|
function cont() {
|
||||||
|
pass.apply(null, arguments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function register(varname) {
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.context) {
|
||||||
|
cx.marked = "def";
|
||||||
|
for (var v = state.localVars; v; v = v.next)
|
||||||
|
if (v.name == varname) return;
|
||||||
|
state.localVars = {name: varname, next: state.localVars};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinators
|
||||||
|
|
||||||
|
var defaultVars = {name: "this", next: {name: "arguments"}};
|
||||||
|
function pushcontext() {
|
||||||
|
if (!cx.state.context) cx.state.localVars = defaultVars;
|
||||||
|
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
|
||||||
|
}
|
||||||
|
function popcontext() {
|
||||||
|
cx.state.localVars = cx.state.context.vars;
|
||||||
|
cx.state.context = cx.state.context.prev;
|
||||||
|
}
|
||||||
|
function pushlex(type, info) {
|
||||||
|
var result = function() {
|
||||||
|
var state = cx.state;
|
||||||
|
state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)
|
||||||
|
};
|
||||||
|
result.lex = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function poplex() {
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.lexical.prev) {
|
||||||
|
if (state.lexical.type == ")")
|
||||||
|
state.indented = state.lexical.indented;
|
||||||
|
state.lexical = state.lexical.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poplex.lex = true;
|
||||||
|
|
||||||
|
function expect(wanted) {
|
||||||
|
return function expecting(type) {
|
||||||
|
if (type == wanted) return cont();
|
||||||
|
else if (wanted == ";") return pass();
|
||||||
|
else return cont(arguments.callee);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function statement(type) {
|
||||||
|
if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
|
||||||
|
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
||||||
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||||
|
if (type == "{") return cont(pushlex("}"), block, poplex);
|
||||||
|
if (type == ";") return cont();
|
||||||
|
if (type == "function") return cont(functiondef);
|
||||||
|
if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
|
||||||
|
poplex, statement, poplex);
|
||||||
|
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
||||||
|
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
||||||
|
block, poplex, poplex);
|
||||||
|
if (type == "case") return cont(expression, expect(":"));
|
||||||
|
if (type == "default") return cont(expect(":"));
|
||||||
|
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
||||||
|
statement, poplex, popcontext);
|
||||||
|
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function expression(type) {
|
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
|
||||||
|
if (type == "function") return cont(functiondef);
|
||||||
|
if (type == "keyword c") return cont(maybeexpression);
|
||||||
|
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
|
||||||
|
if (type == "operator") return cont(expression);
|
||||||
|
if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
|
||||||
|
if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function maybeexpression(type) {
|
||||||
|
if (type.match(/[;\}\)\],]/)) return pass();
|
||||||
|
return pass(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeoperator(type, value) {
|
||||||
|
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
|
||||||
|
if (type == "operator") return cont(expression);
|
||||||
|
if (type == ";") return;
|
||||||
|
if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
|
||||||
|
if (type == ".") return cont(property, maybeoperator);
|
||||||
|
if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
|
||||||
|
}
|
||||||
|
function maybelabel(type) {
|
||||||
|
if (type == ":") return cont(poplex, statement);
|
||||||
|
return pass(maybeoperator, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function property(type) {
|
||||||
|
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||||
|
}
|
||||||
|
function objprop(type) {
|
||||||
|
if (type == "variable") cx.marked = "property";
|
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
|
||||||
|
}
|
||||||
|
function commasep(what, end) {
|
||||||
|
function proceed(type) {
|
||||||
|
if (type == ",") return cont(what, proceed);
|
||||||
|
if (type == end) return cont();
|
||||||
|
return cont(expect(end));
|
||||||
|
}
|
||||||
|
return function commaSeparated(type) {
|
||||||
|
if (type == end) return cont();
|
||||||
|
else return pass(what, proceed);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function block(type) {
|
||||||
|
if (type == "}") return cont();
|
||||||
|
return pass(statement, block);
|
||||||
|
}
|
||||||
|
function vardef1(type, value) {
|
||||||
|
if (type == "variable"){register(value); return cont(vardef2);}
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function vardef2(type, value) {
|
||||||
|
if (value == "=") return cont(expression, vardef2);
|
||||||
|
if (type == ",") return cont(vardef1);
|
||||||
|
}
|
||||||
|
function forspec1(type) {
|
||||||
|
if (type == "var") return cont(vardef1, forspec2);
|
||||||
|
if (type == ";") return pass(forspec2);
|
||||||
|
if (type == "variable") return cont(formaybein);
|
||||||
|
return pass(forspec2);
|
||||||
|
}
|
||||||
|
function formaybein(type, value) {
|
||||||
|
if (value == "in") return cont(expression);
|
||||||
|
return cont(maybeoperator, forspec2);
|
||||||
|
}
|
||||||
|
function forspec2(type, value) {
|
||||||
|
if (type == ";") return cont(forspec3);
|
||||||
|
if (value == "in") return cont(expression);
|
||||||
|
return cont(expression, expect(";"), forspec3);
|
||||||
|
}
|
||||||
|
function forspec3(type) {
|
||||||
|
if (type != ")") cont(expression);
|
||||||
|
}
|
||||||
|
function functiondef(type, value) {
|
||||||
|
if (type == "variable") {register(value); return cont(functiondef);}
|
||||||
|
if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
|
||||||
|
}
|
||||||
|
function funarg(type, value) {
|
||||||
|
if (type == "variable") {register(value); return cont();}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(basecolumn) {
|
||||||
|
return {
|
||||||
|
tokenize: jsTokenBase,
|
||||||
|
reAllowed: true,
|
||||||
|
kwAllowed: true,
|
||||||
|
cc: [],
|
||||||
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||||
|
localVars: null,
|
||||||
|
context: null,
|
||||||
|
indented: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (stream.sol()) {
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = false;
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
}
|
||||||
|
if (stream.eatSpace()) return null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if (type == "comment") return style;
|
||||||
|
state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
|
||||||
|
state.kwAllowed = type != '.';
|
||||||
|
return parseJS(state, style, type, content, stream);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (state.tokenize != jsTokenBase) return 0;
|
||||||
|
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
|
||||||
|
type = lexical.type, closing = firstChar == type;
|
||||||
|
if (type == "vardef") return lexical.indented + 4;
|
||||||
|
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||||
|
else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
|
||||||
|
else if (lexical.info == "switch" && !closing)
|
||||||
|
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||||
|
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||||
|
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||||
|
},
|
||||||
|
|
||||||
|
electricChars: ":{}"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
|
487
node_modules/esprima/assets/json2.js
generated
vendored
Normal file
487
node_modules/esprima/assets/json2.js
generated
vendored
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
http://www.JSON.org/json2.js
|
||||||
|
2011-10-19
|
||||||
|
|
||||||
|
Public Domain.
|
||||||
|
|
||||||
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||||
|
|
||||||
|
See http://www.JSON.org/js.html
|
||||||
|
|
||||||
|
|
||||||
|
This code should be minified before deployment.
|
||||||
|
See http://javascript.crockford.com/jsmin.html
|
||||||
|
|
||||||
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||||
|
NOT CONTROL.
|
||||||
|
|
||||||
|
|
||||||
|
This file creates a global JSON object containing two methods: stringify
|
||||||
|
and parse.
|
||||||
|
|
||||||
|
JSON.stringify(value, replacer, space)
|
||||||
|
value any JavaScript value, usually an object or array.
|
||||||
|
|
||||||
|
replacer an optional parameter that determines how object
|
||||||
|
values are stringified for objects. It can be a
|
||||||
|
function or an array of strings.
|
||||||
|
|
||||||
|
space an optional parameter that specifies the indentation
|
||||||
|
of nested structures. If it is omitted, the text will
|
||||||
|
be packed without extra whitespace. If it is a number,
|
||||||
|
it will specify the number of spaces to indent at each
|
||||||
|
level. If it is a string (such as '\t' or ' '),
|
||||||
|
it contains the characters used to indent at each level.
|
||||||
|
|
||||||
|
This method produces a JSON text from a JavaScript value.
|
||||||
|
|
||||||
|
When an object value is found, if the object contains a toJSON
|
||||||
|
method, its toJSON method will be called and the result will be
|
||||||
|
stringified. A toJSON method does not serialize: it returns the
|
||||||
|
value represented by the name/value pair that should be serialized,
|
||||||
|
or undefined if nothing should be serialized. The toJSON method
|
||||||
|
will be passed the key associated with the value, and this will be
|
||||||
|
bound to the value
|
||||||
|
|
||||||
|
For example, this would serialize Dates as ISO strings.
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
You can provide an optional replacer method. It will be passed the
|
||||||
|
key and value of each member, with this bound to the containing
|
||||||
|
object. The value that is returned from your method will be
|
||||||
|
serialized. If your method returns undefined, then the member will
|
||||||
|
be excluded from the serialization.
|
||||||
|
|
||||||
|
If the replacer parameter is an array of strings, then it will be
|
||||||
|
used to select the members to be serialized. It filters the results
|
||||||
|
such that only members with keys listed in the replacer array are
|
||||||
|
stringified.
|
||||||
|
|
||||||
|
Values that do not have JSON representations, such as undefined or
|
||||||
|
functions, will not be serialized. Such values in objects will be
|
||||||
|
dropped; in arrays they will be replaced with null. You can use
|
||||||
|
a replacer function to replace those with JSON values.
|
||||||
|
JSON.stringify(undefined) returns undefined.
|
||||||
|
|
||||||
|
The optional space parameter produces a stringification of the
|
||||||
|
value that is filled with line breaks and indentation to make it
|
||||||
|
easier to read.
|
||||||
|
|
||||||
|
If the space parameter is a non-empty string, then that string will
|
||||||
|
be used for indentation. If the space parameter is a number, then
|
||||||
|
the indentation will be that many spaces.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||||
|
// text is '["e",{"pluribus":"unum"}]'
|
||||||
|
|
||||||
|
|
||||||
|
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||||
|
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||||
|
|
||||||
|
text = JSON.stringify([new Date()], function (key, value) {
|
||||||
|
return this[key] instanceof Date ?
|
||||||
|
'Date(' + this[key] + ')' : value;
|
||||||
|
});
|
||||||
|
// text is '["Date(---current time---)"]'
|
||||||
|
|
||||||
|
|
||||||
|
JSON.parse(text, reviver)
|
||||||
|
This method parses a JSON text to produce an object or array.
|
||||||
|
It can throw a SyntaxError exception.
|
||||||
|
|
||||||
|
The optional reviver parameter is a function that can filter and
|
||||||
|
transform the results. It receives each of the keys and values,
|
||||||
|
and its return value is used instead of the original value.
|
||||||
|
If it returns what it received, then the structure is not modified.
|
||||||
|
If it returns undefined then the member is deleted.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
// Parse the text. Values that look like ISO date strings will
|
||||||
|
// be converted to Date objects.
|
||||||
|
|
||||||
|
myData = JSON.parse(text, function (key, value) {
|
||||||
|
var a;
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
a =
|
||||||
|
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||||
|
if (a) {
|
||||||
|
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||||
|
+a[5], +a[6]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||||
|
var d;
|
||||||
|
if (typeof value === 'string' &&
|
||||||
|
value.slice(0, 5) === 'Date(' &&
|
||||||
|
value.slice(-1) === ')') {
|
||||||
|
d = new Date(value.slice(5, -1));
|
||||||
|
if (d) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
This is a reference implementation. You are free to copy, modify, or
|
||||||
|
redistribute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*jslint evil: true, regexp: true */
|
||||||
|
|
||||||
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||||
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||||
|
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||||
|
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||||
|
test, toJSON, toString, valueOf
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Create a JSON object only if one does not already exist. We create the
|
||||||
|
// methods in a closure to avoid creating global variables.
|
||||||
|
|
||||||
|
var JSON;
|
||||||
|
if (!JSON) {
|
||||||
|
JSON = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function f(n) {
|
||||||
|
// Format integers to have at least two digits.
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Date.prototype.toJSON !== 'function') {
|
||||||
|
|
||||||
|
Date.prototype.toJSON = function (key) {
|
||||||
|
|
||||||
|
return isFinite(this.valueOf())
|
||||||
|
? this.getUTCFullYear() + '-' +
|
||||||
|
f(this.getUTCMonth() + 1) + '-' +
|
||||||
|
f(this.getUTCDate()) + 'T' +
|
||||||
|
f(this.getUTCHours()) + ':' +
|
||||||
|
f(this.getUTCMinutes()) + ':' +
|
||||||
|
f(this.getUTCSeconds()) + 'Z'
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.toJSON =
|
||||||
|
Number.prototype.toJSON =
|
||||||
|
Boolean.prototype.toJSON = function (key) {
|
||||||
|
return this.valueOf();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cx = new RegExp('/[\u0000\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]', 'g'),
|
||||||
|
escapable = new RegExp('/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]', 'g'),
|
||||||
|
gap,
|
||||||
|
indent,
|
||||||
|
meta = { // table of character substitutions
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
},
|
||||||
|
rep;
|
||||||
|
|
||||||
|
|
||||||
|
function quote(string) {
|
||||||
|
|
||||||
|
// If the string contains no control characters, no quote characters, and no
|
||||||
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
|
// sequences.
|
||||||
|
|
||||||
|
escapable.lastIndex = 0;
|
||||||
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
||||||
|
var c = meta[a];
|
||||||
|
return typeof c === 'string'
|
||||||
|
? c
|
||||||
|
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
}) + '"' : '"' + string + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function str(key, holder) {
|
||||||
|
|
||||||
|
// Produce a string from holder[key].
|
||||||
|
|
||||||
|
var i, // The loop counter.
|
||||||
|
k, // The member key.
|
||||||
|
v, // The member value.
|
||||||
|
length,
|
||||||
|
mind = gap,
|
||||||
|
partial,
|
||||||
|
value = holder[key];
|
||||||
|
|
||||||
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||||
|
|
||||||
|
if (value && typeof value === 'object' &&
|
||||||
|
typeof value.toJSON === 'function') {
|
||||||
|
value = value.toJSON(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were called with a replacer function, then call the replacer to
|
||||||
|
// obtain a replacement value.
|
||||||
|
|
||||||
|
if (typeof rep === 'function') {
|
||||||
|
value = rep.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// What happens next depends on the value's type.
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string':
|
||||||
|
return quote(value);
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
|
||||||
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||||
|
|
||||||
|
return isFinite(value) ? String(value) : 'null';
|
||||||
|
|
||||||
|
case 'boolean':
|
||||||
|
case 'null':
|
||||||
|
|
||||||
|
// If the value is a boolean or null, convert it to a string. Note:
|
||||||
|
// typeof null does not produce 'null'. The case is included here in
|
||||||
|
// the remote chance that this gets fixed someday.
|
||||||
|
|
||||||
|
return String(value);
|
||||||
|
|
||||||
|
// If the type is 'object', we might be dealing with an object or an array or
|
||||||
|
// null.
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
|
||||||
|
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||||
|
// so watch out for that case.
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array to hold the partial results of stringifying this object value.
|
||||||
|
|
||||||
|
gap += indent;
|
||||||
|
partial = [];
|
||||||
|
|
||||||
|
// Is the value an array?
|
||||||
|
|
||||||
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||||
|
|
||||||
|
// The value is an array. Stringify every element. Use null as a placeholder
|
||||||
|
// for non-JSON values.
|
||||||
|
|
||||||
|
length = value.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
partial[i] = str(i, value) || 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the elements together, separated with commas, and wrap them in
|
||||||
|
// brackets.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '[]'
|
||||||
|
: gap
|
||||||
|
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
|
||||||
|
: '[' + partial.join(',') + ']';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the replacer is an array, use it to select the members to be stringified.
|
||||||
|
|
||||||
|
if (rep && typeof rep === 'object') {
|
||||||
|
length = rep.length;
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
if (typeof rep[i] === 'string') {
|
||||||
|
k = rep[i];
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Otherwise, iterate through all of the keys in the object.
|
||||||
|
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = str(k, value);
|
||||||
|
if (v) {
|
||||||
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all of the member texts together, separated with commas,
|
||||||
|
// and wrap them in braces.
|
||||||
|
|
||||||
|
v = partial.length === 0
|
||||||
|
? '{}'
|
||||||
|
: gap
|
||||||
|
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
|
||||||
|
: '{' + partial.join(',') + '}';
|
||||||
|
gap = mind;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a stringify method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.stringify !== 'function') {
|
||||||
|
JSON.stringify = function (value, replacer, space) {
|
||||||
|
|
||||||
|
// The stringify method takes a value and an optional replacer, and an optional
|
||||||
|
// space parameter, and returns a JSON text. The replacer can be a function
|
||||||
|
// that can replace values, or an array of strings that will select the keys.
|
||||||
|
// A default replacer method can be provided. Use of the space parameter can
|
||||||
|
// produce text that is more easily readable.
|
||||||
|
|
||||||
|
var i;
|
||||||
|
gap = '';
|
||||||
|
indent = '';
|
||||||
|
|
||||||
|
// If the space parameter is a number, make an indent string containing that
|
||||||
|
// many spaces.
|
||||||
|
|
||||||
|
if (typeof space === 'number') {
|
||||||
|
for (i = 0; i < space; i += 1) {
|
||||||
|
indent += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the space parameter is a string, it will be used as the indent string.
|
||||||
|
|
||||||
|
} else if (typeof space === 'string') {
|
||||||
|
indent = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a replacer, it must be a function or an array.
|
||||||
|
// Otherwise, throw an error.
|
||||||
|
|
||||||
|
rep = replacer;
|
||||||
|
if (replacer && typeof replacer !== 'function' &&
|
||||||
|
(typeof replacer !== 'object' ||
|
||||||
|
typeof replacer.length !== 'number')) {
|
||||||
|
throw new Error('JSON.stringify');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a fake root object containing our value under the key of ''.
|
||||||
|
// Return the result of stringifying the value.
|
||||||
|
|
||||||
|
return str('', {'': value});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If the JSON object does not yet have a parse method, give it one.
|
||||||
|
|
||||||
|
if (typeof JSON.parse !== 'function') {
|
||||||
|
JSON.parse = function (text, reviver) {
|
||||||
|
|
||||||
|
// The parse method takes a text and an optional reviver function, and returns
|
||||||
|
// a JavaScript value if the text is a valid JSON text.
|
||||||
|
|
||||||
|
var j;
|
||||||
|
|
||||||
|
function walk(holder, key) {
|
||||||
|
|
||||||
|
// The walk method is used to recursively walk the resulting structure so
|
||||||
|
// that modifications can be made.
|
||||||
|
|
||||||
|
var k, v, value = holder[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
for (k in value) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||||
|
v = walk(value, k);
|
||||||
|
if (v !== undefined) {
|
||||||
|
value[k] = v;
|
||||||
|
} else {
|
||||||
|
delete value[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reviver.call(holder, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parsing happens in four stages. In the first stage, we replace certain
|
||||||
|
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||||
|
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||||
|
|
||||||
|
text = String(text);
|
||||||
|
cx.lastIndex = 0;
|
||||||
|
if (cx.test(text)) {
|
||||||
|
text = text.replace(cx, function (a) {
|
||||||
|
return '\\u' +
|
||||||
|
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the second stage, we run the text against regular expressions that look
|
||||||
|
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||||
|
// because they can cause invocation, and '=' because it can cause mutation.
|
||||||
|
// But just to be safe, we want to reject all unexpected forms.
|
||||||
|
|
||||||
|
// We split the second stage into 4 regexp operations in order to work around
|
||||||
|
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||||
|
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||||
|
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||||
|
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||||
|
// we look to see that the remaining characters are only whitespace or ']' or
|
||||||
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/
|
||||||
|
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||||
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||||
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||||
|
|
||||||
|
// In the third stage we use the eval function to compile the text into a
|
||||||
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||||
|
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||||
|
// in parens to eliminate the ambiguity.
|
||||||
|
|
||||||
|
j = eval('(' + text + ')');
|
||||||
|
|
||||||
|
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||||
|
// each name/value pair to a reviver function for possible transformation.
|
||||||
|
|
||||||
|
return typeof reviver === 'function'
|
||||||
|
? walk({'': j}, '')
|
||||||
|
: j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||||
|
|
||||||
|
throw new SyntaxError('JSON.parse');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}());
|
164
node_modules/esprima/assets/style.css
generated
vendored
Normal file
164
node_modules/esprima/assets/style.css
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
body {
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-width: 960px;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #444;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-bottom: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-left: 15px;
|
||||||
|
font-family: Inconsolata, Menlo, 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 36px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 small {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3, h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
border-left: 3px solid #ddd;
|
||||||
|
margin: 5px 3px 8px 15px;
|
||||||
|
padding: 0 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 960px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar {
|
||||||
|
top: 0;
|
||||||
|
margin: 0 0 0 480px;
|
||||||
|
padding: 0;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar ul {
|
||||||
|
padding: 5px 20px 5px 10px;
|
||||||
|
background-color: #222;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar a {
|
||||||
|
color: #ddd;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar a:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar .nav li {
|
||||||
|
background-color: #222;
|
||||||
|
display: inline;
|
||||||
|
padding: 4px 10px 4px 0px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container .main {
|
||||||
|
width: 540px;
|
||||||
|
display: inline;
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container .sidebar {
|
||||||
|
width: 350px;
|
||||||
|
display: inline;
|
||||||
|
float: left;
|
||||||
|
margin-left: 30px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 25px;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
color: #555;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-family: Inconsolata, Monaco, Consolas, "Lucida Console", monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #555;
|
||||||
|
width: 80%;
|
||||||
|
padding: 7px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 80%;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
padding: 3px 3px 10px 3px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(odd) td {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
42
node_modules/esprima/bin/esparse.js
generated
vendored
Executable file
42
node_modules/esprima/bin/esparse.js
generated
vendored
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/*
|
||||||
|
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 */
|
||||||
|
|
||||||
|
var fs = require('fs'),
|
||||||
|
esprima = require('esprima'),
|
||||||
|
files = process.argv.splice(2);
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
|
console.log('Usage:');
|
||||||
|
console.log(' esparse file.js');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
files.forEach(function (filename) {
|
||||||
|
var content = fs.readFileSync(filename, 'utf-8');
|
||||||
|
console.log(JSON.stringify(esprima.parse(content), null, 4));
|
||||||
|
});
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
42
node_modules/esprima/demo/checkenv.js
generated
vendored
Normal file
42
node_modules/esprima/demo/checkenv.js
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unfortunately we have to use User Agent detection to blacklist the browsers.
|
||||||
|
/*jslint browser:true */
|
||||||
|
(function (window) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var majorVersion = parseInt(window.platform.version.split('.')[0], 10);
|
||||||
|
|
||||||
|
window.checkEnv = function () {
|
||||||
|
if (window.platform.name === 'Safari' && majorVersion <= 3) {
|
||||||
|
throw new Error('CodeMirror does not support Safari <= 3');
|
||||||
|
}
|
||||||
|
if (window.platform.name === 'Opera' && majorVersion <= 8) {
|
||||||
|
throw new Error('CodeMirror does not support Opera <= 8');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}(window));
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
82
node_modules/esprima/demo/collector.html
generated
vendored
Normal file
82
node_modules/esprima/demo/collector.html
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Regex Collector Demo</title>
|
||||||
|
<script src="../test/3rdparty/platform.js"></script>
|
||||||
|
<script src="checkenv.js"></script>
|
||||||
|
<script src="collector.js"></script>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/codemirror/codemirror.js"></script>
|
||||||
|
<script src="../assets/codemirror/javascript.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/codemirror/codemirror.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Regular Expression Collector <small>uncovers all your secrets</small></h1>
|
||||||
|
|
||||||
|
<p><strong>Note</strong>: Only regular expression literals and objects created with <code>RegExp</code> are considered.</p>
|
||||||
|
<p>Type ECMAScript code:</p>
|
||||||
|
<p><textarea id="code" autofocus="autofocus" cols="70" rows="15" spellcheck="false">
|
||||||
|
var letterRE = new RegExp('[a-zA-Z]', 'g'),
|
||||||
|
digitRE = RegExp('[0-9]');
|
||||||
|
|
||||||
|
|
||||||
|
// This is from json2.js.
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||||
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||||
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||||
|
}
|
||||||
|
</textarea></p>
|
||||||
|
<p id="codemirror" align="right"><small>The above code editor is based on <a href="http://codemirror.net" target="_blank">CodeMirror</a>.</small></p>
|
||||||
|
|
||||||
|
<p>Using Esprima version <span id="version"></span>.</p>
|
||||||
|
|
||||||
|
<div id="result">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="testbox" style="visibility: hidden;"><textarea id="test"></textarea></p>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
/*jslint sloppy:true browser:true */
|
||||||
|
/*global collectRegex:true, CodeMirror:true */
|
||||||
|
window.onload = collectRegex;
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.checkEnv();
|
||||||
|
|
||||||
|
// This is just testing, to detect whether CodeMirror would fail or not
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("test"));
|
||||||
|
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||||
|
lineNumbers: true,
|
||||||
|
matchBrackets: true,
|
||||||
|
onChange: collectRegex
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// CodeMirror failed to initialize, possible in e.g. old IE.
|
||||||
|
document.getElementById('codemirror').innerHTML = '';
|
||||||
|
document.getElementById('code').onchange = collectRegex;
|
||||||
|
document.getElementById('code').onkeydown = collectRegex;
|
||||||
|
} finally {
|
||||||
|
document.getElementById('testbox').parentNode.removeChild(document.getElementById('testbox'));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
170
node_modules/esprima/demo/collector.js
generated
vendored
Normal file
170
node_modules/esprima/demo/collector.js
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
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 browser:true */
|
||||||
|
|
||||||
|
var timerId;
|
||||||
|
|
||||||
|
function collectRegex() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function id(i) {
|
||||||
|
return document.getElementById(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function escaped(str) {
|
||||||
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(id, str) {
|
||||||
|
var el = document.getElementById(id);
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = str;
|
||||||
|
} else {
|
||||||
|
el.textContent = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLineTerminator(ch) {
|
||||||
|
return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
|
||||||
|
}
|
||||||
|
|
||||||
|
function process(delay) {
|
||||||
|
if (timerId) {
|
||||||
|
window.clearTimeout(timerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
timerId = window.setTimeout(function () {
|
||||||
|
var code, result, i, str;
|
||||||
|
|
||||||
|
if (typeof window.editor === 'undefined') {
|
||||||
|
code = document.getElementById('code').value;
|
||||||
|
} else {
|
||||||
|
code = window.editor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes f on the object and its children (recursively).
|
||||||
|
function visit(object, f) {
|
||||||
|
var key, child;
|
||||||
|
|
||||||
|
if (f.call(null, object) === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (key in object) {
|
||||||
|
if (object.hasOwnProperty(key)) {
|
||||||
|
child = object[key];
|
||||||
|
if (typeof child === 'object' && child !== null) {
|
||||||
|
visit(child, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRegex(pattern, mode) {
|
||||||
|
var literal;
|
||||||
|
try {
|
||||||
|
literal = new RegExp(pattern, mode);
|
||||||
|
} catch (e) {
|
||||||
|
// Invalid regular expression.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
function collect(node) {
|
||||||
|
var str, arg, value;
|
||||||
|
if (node.type === 'Literal') {
|
||||||
|
if (node.value instanceof RegExp) {
|
||||||
|
str = node.value.toString();
|
||||||
|
if (str[0] === '/') {
|
||||||
|
result.push({
|
||||||
|
type: 'Literal',
|
||||||
|
value: node.value,
|
||||||
|
line: node.loc.start.line,
|
||||||
|
column: node.loc.start.column
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.type === 'NewExpression' || node.type === 'CallExpression') {
|
||||||
|
if (node.callee.type === 'Identifier' && node.callee.name === 'RegExp') {
|
||||||
|
arg = node['arguments'];
|
||||||
|
if (arg.length === 1 && arg[0].type === 'Literal') {
|
||||||
|
if (typeof arg[0].value === 'string') {
|
||||||
|
value = createRegex(arg[0].value);
|
||||||
|
if (value) {
|
||||||
|
result.push({
|
||||||
|
type: 'Literal',
|
||||||
|
value: value,
|
||||||
|
line: node.loc.start.line,
|
||||||
|
column: node.loc.start.column
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arg.length === 2 && arg[0].type === 'Literal' && arg[1].type === 'Literal') {
|
||||||
|
if (typeof arg[0].value === 'string' && typeof arg[1].value === 'string') {
|
||||||
|
value = createRegex(arg[0].value, arg[1].value);
|
||||||
|
if (value) {
|
||||||
|
result.push({
|
||||||
|
type: 'Literal',
|
||||||
|
value: value,
|
||||||
|
line: node.loc.start.line,
|
||||||
|
column: node.loc.start.column
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = [];
|
||||||
|
visit(window.esprima.parse(code, { loc: true }), collect);
|
||||||
|
|
||||||
|
if (result.length > 0) {
|
||||||
|
str = '<p>Found <b>' + result.length + '</b> regex(s):</p>';
|
||||||
|
for (i = 0; i < result.length; i += 1) {
|
||||||
|
str += '<p>' + 'Line ' + result[i].line;
|
||||||
|
str += ' column ' + (1 + result[i].column);
|
||||||
|
str += ': <code>'; str += escaped(result[i].value.toString()) + '</code>';
|
||||||
|
str += '</p>';
|
||||||
|
}
|
||||||
|
id('result').innerHTML = str;
|
||||||
|
} else {
|
||||||
|
setText('result', 'No regex.');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setText('result', e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
timerId = undefined;
|
||||||
|
}, delay || 811);
|
||||||
|
}
|
||||||
|
|
||||||
|
setText('version', window.esprima.version);
|
||||||
|
process(1);
|
||||||
|
}
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
105
node_modules/esprima/demo/functiontrace.html
generated
vendored
Normal file
105
node_modules/esprima/demo/functiontrace.html
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Function Trace Demo</title>
|
||||||
|
<script src="../test/3rdparty/platform.js"></script>
|
||||||
|
<script src="checkenv.js"></script>
|
||||||
|
<script src="functiontrace.js"></script>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/codemirror/codemirror.js"></script>
|
||||||
|
<script src="../assets/codemirror/javascript.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/codemirror/codemirror.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<style>
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Function Trace <small>reveals what is being called</small></h1>
|
||||||
|
|
||||||
|
<p>Type ECMAScript code:</p>
|
||||||
|
<p><textarea id="code" autofocus="autofocus" cols="70" rows="25" spellcheck="false">
|
||||||
|
Array.prototype.swap = function (i, j) {
|
||||||
|
var k = this[i]; this[i] = this[j]; this[j] = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bubbleSort(list) {
|
||||||
|
var items = list.slice(0), swapped = false, p, q;
|
||||||
|
for (p = 1; p < items.length; ++p) {
|
||||||
|
for (q = 0; q < items.length - p; ++q) {
|
||||||
|
if (items[q + 1] < items[q]) {
|
||||||
|
items.swap(q, q + 1);
|
||||||
|
swapped =true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!swapped) break;
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
var N = 100, data = []; while (N > 0) data.push(N--);
|
||||||
|
|
||||||
|
bubbleSort(data);
|
||||||
|
</textarea></p>
|
||||||
|
<p id="codemirror" align="right"><small>The above code editor is based on <a href="http://codemirror.net" target="_blank">CodeMirror</a>.</small></p>
|
||||||
|
|
||||||
|
<p><input type="button" value="Run" id="run"></p>
|
||||||
|
|
||||||
|
<div id="result"><p>No result yet.</p></div>
|
||||||
|
|
||||||
|
<p style="margin-top: 50px;">Using Esprima version <span id="version"></span>.</p>
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="testbox" style="visibility: hidden;"><textarea id="test"></textarea></p>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
/*jslint sloppy:true browser:true */
|
||||||
|
/*global traceRun:true, CodeMirror:true */
|
||||||
|
window.onload = function () {
|
||||||
|
var el;
|
||||||
|
|
||||||
|
el = document.getElementById('version');
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = window.esprima.version;
|
||||||
|
} else {
|
||||||
|
el.textContent = window.esprima.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('run').onclick = traceRun;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.checkEnv();
|
||||||
|
|
||||||
|
// This is just testing, to detect whether CodeMirror would fail or not
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("test"));
|
||||||
|
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||||
|
lineNumbers: true,
|
||||||
|
matchBrackets: true
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// CodeMirror failed to initialize, possible in e.g. old IE.
|
||||||
|
document.getElementById('codemirror').innerHTML = '';
|
||||||
|
} finally {
|
||||||
|
document.getElementById('testbox').parentNode.removeChild(document.getElementById('testbox'));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
123
node_modules/esprima/demo/functiontrace.js
generated
vendored
Normal file
123
node_modules/esprima/demo/functiontrace.js
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
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 browser:true evil:true */
|
||||||
|
|
||||||
|
var timerId;
|
||||||
|
|
||||||
|
function traceRun() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var lookup;
|
||||||
|
|
||||||
|
function id(i) {
|
||||||
|
return document.getElementById(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function escaped(str) {
|
||||||
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(id, str) {
|
||||||
|
var el = document.getElementById(id);
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = str;
|
||||||
|
} else {
|
||||||
|
el.textContent = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLineTerminator(ch) {
|
||||||
|
return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertTracer() {
|
||||||
|
var tracer, code, i, functionList, signature, pos;
|
||||||
|
|
||||||
|
if (typeof window.editor === 'undefined') {
|
||||||
|
code = document.getElementById('code').value;
|
||||||
|
} else {
|
||||||
|
code = window.editor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
tracer = window.esprima.Tracer.FunctionEntrance('window.TRACE.enterFunction');
|
||||||
|
code = window.esprima.modify(code, tracer);
|
||||||
|
|
||||||
|
// Enclose in IIFE.
|
||||||
|
code = '(function() {\n' + code + '\n}())';
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResult() {
|
||||||
|
var i, str, histogram, entry;
|
||||||
|
|
||||||
|
histogram = window.TRACE.getHistogram();
|
||||||
|
|
||||||
|
str = '<table><thead><tr><td>Function</td><td>Hits</td></tr></thead>';
|
||||||
|
for (i = 0; i < histogram.length; i += 1) {
|
||||||
|
entry = histogram[i];
|
||||||
|
str += '<tr>';
|
||||||
|
str += '<td>' + entry.name + '</td>';
|
||||||
|
str += '<td>' + entry.count + '</td>';
|
||||||
|
str += '</tr>';
|
||||||
|
}
|
||||||
|
str += '</table>';
|
||||||
|
|
||||||
|
id('result').innerHTML = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.TRACE = {
|
||||||
|
hits: {},
|
||||||
|
enterFunction: function (info) {
|
||||||
|
var key = info.name + ' at line ' + info.lineNumber;
|
||||||
|
if (this.hits.hasOwnProperty(key)) {
|
||||||
|
this.hits[key] = this.hits[key] + 1;
|
||||||
|
} else {
|
||||||
|
this.hits[key] = 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getHistogram: function () {
|
||||||
|
var entry,
|
||||||
|
sorted = [];
|
||||||
|
for (entry in this.hits) {
|
||||||
|
if (this.hits.hasOwnProperty(entry)) {
|
||||||
|
sorted.push({ name: entry, count: this.hits[entry]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sorted.sort(function (a, b) {
|
||||||
|
return b.count - a.count;
|
||||||
|
});
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
eval(insertTracer());
|
||||||
|
showResult();
|
||||||
|
} catch (e) {
|
||||||
|
id('result').innerText = e.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
82
node_modules/esprima/demo/parse.css
generated
vendored
Normal file
82
node_modules/esprima/demo/parse.css
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
.tabs textarea {
|
||||||
|
padding: 7px 0px 7px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
margin-top: 30px;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs ul, .tabs li {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs h3 {
|
||||||
|
float: left;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 6px 0 0;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
background-color: #eee;
|
||||||
|
border-bottom: none;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 0;
|
||||||
|
-moz-border-radius-topleft: 6px;
|
||||||
|
-webkit-border-top-left-radius: 6px;
|
||||||
|
-ms-border-top-left-radius: 6px;
|
||||||
|
-o-border-top-left-radius: 6px;
|
||||||
|
border-top-left-radius: 6px;
|
||||||
|
-moz-border-radius-topright: 6px;
|
||||||
|
-webkit-border-top-right-radius: 6px;
|
||||||
|
-ms-border-top-right-radius: 6px;
|
||||||
|
-o-border-top-right-radius: 6px;
|
||||||
|
border-top-right-radius: 6px
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .active h3 {
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
z-index: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs h3 a {
|
||||||
|
padding: 0 10px;
|
||||||
|
line-height: 29px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs a {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs a:visited {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .tab {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
left: 0;
|
||||||
|
top: 29px;
|
||||||
|
right: 0;
|
||||||
|
border-top: 1px solid #bbb;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 25px 60px 50px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pages div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pages div.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .active .tab {
|
||||||
|
display: block;
|
||||||
|
}
|
190
node_modules/esprima/demo/parse.html
generated
vendored
Normal file
190
node_modules/esprima/demo/parse.html
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Parsing Demo</title>
|
||||||
|
<script src="../test/3rdparty/platform.js"></script>
|
||||||
|
<script src="checkenv.js"></script>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<script src="../assets/codemirror/codemirror.js"></script>
|
||||||
|
<script src="../assets/codemirror/javascript.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/codemirror/codemirror.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="parse.css"/>
|
||||||
|
<script>
|
||||||
|
/*jslint sloppy:true browser:true */
|
||||||
|
/*global esprima:true */
|
||||||
|
var parseId;
|
||||||
|
function parse(delay) {
|
||||||
|
if (parseId) {
|
||||||
|
window.clearTimeout(parseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseId = window.setTimeout(function () {
|
||||||
|
var code, options, result, el, str;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window.editor === 'undefined') {
|
||||||
|
code = document.getElementById('code').value;
|
||||||
|
} else {
|
||||||
|
code = window.editor.getValue();
|
||||||
|
}
|
||||||
|
options = {
|
||||||
|
comment: document.getElementById('comment').checked,
|
||||||
|
raw: document.getElementById('raw').checked,
|
||||||
|
range: document.getElementById('range').checked,
|
||||||
|
loc: document.getElementById('loc').checked
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('tokens').value = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
result = esprima.parse(code, options);
|
||||||
|
str = JSON.stringify(result, adjustRegexLiteral, 4);
|
||||||
|
document.getElementById('tokens').value = JSON.stringify(esprima.parse(code,
|
||||||
|
{ tokens : true }).tokens, adjustRegexLiteral, 4);
|
||||||
|
} catch (e) {
|
||||||
|
str = e.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
el = document.getElementById('syntax');
|
||||||
|
el.value = str;
|
||||||
|
|
||||||
|
parseId = undefined;
|
||||||
|
}, delay || 811);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Parser <small>produces syntax tree</small></h1>
|
||||||
|
|
||||||
|
<p>Esprima version <span id="version"></span>.</p>
|
||||||
|
|
||||||
|
<p>Type ECMAScript code:</p>
|
||||||
|
<p><textarea id="code" autofocus="autofocus" cols="70" rows="15" spellcheck="false">
|
||||||
|
// Life, Universe, and Everything
|
||||||
|
var answer = 6 * 7;</textarea></p>
|
||||||
|
<p id="codemirror" align="right"><small>The above code editor is based on <a href="http://codemirror.net" target="_blank">CodeMirror</a>.</small></p>
|
||||||
|
<p><label><input type="checkbox" id="raw"> Preserve raw value of literals</label></p>
|
||||||
|
<p><label><input type="checkbox" id="comment"> Include comments</label></p>
|
||||||
|
<p> Syntax node location info (start, end)</p>
|
||||||
|
<div style="margin-left: 20px;">
|
||||||
|
<p><label><input type="checkbox" id="range">Index-based range</label></p>
|
||||||
|
<p><label><input type="checkbox" id="loc">Line and column-based</label></p>
|
||||||
|
</div>
|
||||||
|
<div class="tabs">
|
||||||
|
<ul>
|
||||||
|
<li id="tab_syntax" class="active">
|
||||||
|
<h3><a id="show_syntax">Syntax</a></h3>
|
||||||
|
<div class="tab">
|
||||||
|
<textarea id="syntax" rows="20" readonly></textarea>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li id="tab_tokens">
|
||||||
|
<h3><a id="show_tokens">Tokens</a></h3>
|
||||||
|
<div class="tab">
|
||||||
|
<textarea id="tokens" rows="20" readonly></textarea>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<p id="testbox"><textarea id="test"></textarea></p>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
var id, el;
|
||||||
|
|
||||||
|
id = function (i) {
|
||||||
|
return document.getElementById(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
el = id('version');
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = esprima.version;
|
||||||
|
} else {
|
||||||
|
el.textContent = esprima.version;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
parse(1);
|
||||||
|
} catch (e) { }
|
||||||
|
|
||||||
|
id('show_syntax').onclick = function () {
|
||||||
|
id('tab_syntax').className = 'active';
|
||||||
|
id('tab_tokens').className = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
id('show_tokens').onclick = function () {
|
||||||
|
id('tab_syntax').className = '';
|
||||||
|
id('tab_tokens').className = 'active';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
/*jslint sloppy:true browser:true */
|
||||||
|
/*global CodeMirror:true */
|
||||||
|
try {
|
||||||
|
function quickParse() { parse(1); }
|
||||||
|
document.getElementById('comment').onchange = quickParse;
|
||||||
|
document.getElementById('raw').onchange = quickParse;
|
||||||
|
document.getElementById('range').onchange = quickParse;
|
||||||
|
document.getElementById('loc').onchange = quickParse;
|
||||||
|
document.getElementById('tokens').onchange = quickParse;
|
||||||
|
|
||||||
|
// Special handling for IE.
|
||||||
|
document.getElementById('comment').onclick = quickParse;
|
||||||
|
document.getElementById('raw').onclick = quickParse;
|
||||||
|
document.getElementById('range').onclick = quickParse;
|
||||||
|
document.getElementById('loc').onclick = quickParse;
|
||||||
|
document.getElementById('tokens').onclick = quickParse;
|
||||||
|
|
||||||
|
window.checkEnv();
|
||||||
|
|
||||||
|
// This is just testing, to detect whether CodeMirror would fail or not
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("test"));
|
||||||
|
|
||||||
|
window.editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||||
|
lineNumbers: true,
|
||||||
|
matchBrackets: true,
|
||||||
|
onChange: parse
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// CodeMirror failed to initialize, possible in e.g. old IE.
|
||||||
|
document.getElementById('codemirror').innerHTML = '';
|
||||||
|
document.getElementById('code').onchange = parse;
|
||||||
|
document.getElementById('code').onkeydown = parse;
|
||||||
|
} finally {
|
||||||
|
document.getElementById('testbox').parentNode.removeChild(document.getElementById('testbox'));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
225
node_modules/esprima/demo/precedence.html
generated
vendored
Normal file
225
node_modules/esprima/demo/precedence.html
generated
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Operator Precedence Demo</title>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<style>
|
||||||
|
#a, #b, #expr {
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#expr {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#answer {
|
||||||
|
color: white;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.yes {
|
||||||
|
background-color: #228B22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no {
|
||||||
|
background-color: #8B2500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightred {
|
||||||
|
background-color: #FFC0CB;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
/*jslint sloppy:true browser:true */
|
||||||
|
/*global esprima:true */
|
||||||
|
var compareId;
|
||||||
|
function compare() {
|
||||||
|
if (compareId) {
|
||||||
|
window.clearTimeout(compareId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringify(node) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
if (typeof node !== 'object') {
|
||||||
|
throw new Error('Node is not valid');
|
||||||
|
}
|
||||||
|
if (typeof node.type !== 'string') {
|
||||||
|
throw new Error('Node does not have type property');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (node.type) {
|
||||||
|
|
||||||
|
case 'Program':
|
||||||
|
if (node.body.length !== 1) {
|
||||||
|
throw new Error('Expression is too complex');
|
||||||
|
}
|
||||||
|
result = stringify(node.body[0]);
|
||||||
|
if (result[0] === '(' && result[result.length - 1] === ')') {
|
||||||
|
result = result.substr(1, result.length - 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'ExpressionStatement':
|
||||||
|
result = stringify(node.expression);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'BinaryExpression':
|
||||||
|
case 'LogicalExpression':
|
||||||
|
result = '(' + stringify(node.left) + ' ' + node.operator + ' ' + stringify(node.right) + ')';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'UnaryExpression':
|
||||||
|
result = '(' + node.operator;
|
||||||
|
if (node.operator.length > 2) {
|
||||||
|
// delete void typeof
|
||||||
|
result += ' ';
|
||||||
|
}
|
||||||
|
result += stringify(node.argument) + ')';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'UpdateExpression':
|
||||||
|
result = stringify(node.argument);
|
||||||
|
if (node.prefix) {
|
||||||
|
result = node.operator + result;
|
||||||
|
} else {
|
||||||
|
result = result + node.operator;
|
||||||
|
}
|
||||||
|
result = '(' + result + ')';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Literal':
|
||||||
|
result = node.value.toString();
|
||||||
|
if (typeof node.value === 'string') {
|
||||||
|
result = '"' + node.value + '"';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Identifier':
|
||||||
|
result = node.name;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Unknown node type: ' + node.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(el, str) {
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = str;
|
||||||
|
} else {
|
||||||
|
el.textContent = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compareId = window.setTimeout(function () {
|
||||||
|
var a, b, answer, status, expr, left, right, suggest;
|
||||||
|
|
||||||
|
a = document.getElementById('a');
|
||||||
|
b = document.getElementById('b');
|
||||||
|
answer = document.getElementById('answer');
|
||||||
|
status = document.getElementById('status');
|
||||||
|
expr = document.getElementById('expr');
|
||||||
|
|
||||||
|
a.setAttribute('class', '');
|
||||||
|
b.setAttribute('class', '');
|
||||||
|
answer.setAttribute('class', '');
|
||||||
|
|
||||||
|
setText(answer, '');
|
||||||
|
setText(status, '');
|
||||||
|
setText(expr, '');
|
||||||
|
|
||||||
|
try {
|
||||||
|
left = esprima.parse((typeof a.innerText === 'string') ? a.innerText : a.textContent);
|
||||||
|
} catch (e_left) {
|
||||||
|
a.setAttribute('class', 'lightred');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
right = esprima.parse((typeof b.innerText === 'string') ? b.innerText : b.textContent);
|
||||||
|
} catch (e_right) {
|
||||||
|
b.setAttribute('class', 'lightred');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
suggest = stringify(left);
|
||||||
|
} catch (e_suggest) {
|
||||||
|
a.setAttribute('class', 'lightred');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && right) {
|
||||||
|
if (JSON.stringify(left) === JSON.stringify(right)) {
|
||||||
|
setText(answer, 'Yes');
|
||||||
|
answer.setAttribute('class', 'yes');
|
||||||
|
} else {
|
||||||
|
setText(answer, 'No');
|
||||||
|
answer.setAttribute('class', 'no');
|
||||||
|
setText(status, suggest ? 'It is more like ' : '');
|
||||||
|
setText(expr, suggest || '');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
answer.setAttribute('class', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
compareId = undefined;
|
||||||
|
}, 57);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Operator precedence <small>is not always easy</small></h1>
|
||||||
|
<p>Is <code id="a" contenteditable="true">1 << 2 * 3</code> semantically equivalent to
|
||||||
|
<code id="b" contenteditable="true">(1 << 2) * 3</code>? <span id="answer"></span></p>
|
||||||
|
<p style="margin-top: 40px;"><span id="status"></span> <code id="expr"></code></p>
|
||||||
|
<p style="margin-top: 60px;">This demo is inspired by <a href="http://mothereff.in/operator-precedence">mothereff.in/operator-precedence</a>.</p>
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
if (typeof document.body.attachEvent === 'object') {
|
||||||
|
// Workaround for old Internet Explorer.
|
||||||
|
// Until there is a reliable way to track the modification to the editable
|
||||||
|
// inputs, manually track the change periodically.
|
||||||
|
window.setInterval(compare, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://mathiasbynens.be/notes/oninput for details.
|
||||||
|
document.getElementById('a').onkeyup = compare;
|
||||||
|
document.getElementById('a').oninput = function () {
|
||||||
|
this.onkeyup = null;
|
||||||
|
compare();
|
||||||
|
};
|
||||||
|
document.getElementById('b').onkeyup = compare;
|
||||||
|
document.getElementById('b').oninput = function () {
|
||||||
|
this.onkeyup = null;
|
||||||
|
compare();
|
||||||
|
};
|
||||||
|
compare();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
4202
node_modules/esprima/esprima.js
generated
vendored
Normal file
4202
node_modules/esprima/esprima.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
92
node_modules/esprima/index.html
generated
vendored
Normal file
92
node_modules/esprima/index.html
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="assets/style.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Esprima <small>ECMAScript parsing infrastructure for multipurpose analysis</small></h1>
|
||||||
|
|
||||||
|
<div class="main">
|
||||||
|
<p>Esprima (<a href="http://esprima.org">esprima.org</a>) is an educational
|
||||||
|
<a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>
|
||||||
|
(also popularly known as <a href="http://en.wikipedia.org/wiki/JavaScript">JavaScript</a>)
|
||||||
|
parsing infrastructure for multipurpose analysis. It is also written in ECMAScript.</p>
|
||||||
|
|
||||||
|
<p>Esprima can be used in a web browser:</p>
|
||||||
|
|
||||||
|
<pre><script src="esprima.js"><script></pre>
|
||||||
|
|
||||||
|
<p>or in a Node.js application via the package manager:</p>
|
||||||
|
|
||||||
|
<pre>npm install esprima</pre>
|
||||||
|
|
||||||
|
<p>Esprima parser output is compatible with Mozilla (SpiderMonkey)
|
||||||
|
<a href="https://developer.mozilla.org/en/SpiderMonkey/Parser_API">Parser API</a>.</p>
|
||||||
|
|
||||||
|
<p>A very simple example:</p>
|
||||||
|
|
||||||
|
<pre>esprima.parse('var answer=42').body[0].declarations[0].init</pre>
|
||||||
|
|
||||||
|
<p>produces the following object:</p>
|
||||||
|
|
||||||
|
<pre>{ type: 'Literal', value: 42 }</pre>
|
||||||
|
|
||||||
|
<p>Esprima is still in the development, for now please check
|
||||||
|
<a href="http://wiki.esprima.org">the wiki documentation</a>.</p>
|
||||||
|
|
||||||
|
<p>Since it is not comprehensive nor complete, refer to the
|
||||||
|
<a href="http://issues.esprima.org">issue tracker</a> for
|
||||||
|
<a href="http://code.google.com/p/esprima/issues/list?q=Defect">known problems</a>
|
||||||
|
and <a href="http://code.google.com/p/esprima/issues/list?q=Enhancement">future plans</a>.
|
||||||
|
Esprima is supported on <a href="http://code.google.com/p/esprima/wiki/BrowserCompatibility">many browsers</a>:
|
||||||
|
IE 6+, Firefox 1+, Safari 3+, Chrome 1+, and Opera 8+.</p>
|
||||||
|
|
||||||
|
<p>Feedback and contribution are welcomed! Please join the
|
||||||
|
<a href="http://groups.google.com/group/esprima">mailing list</a> and read the
|
||||||
|
<a href="http://code.google.com/p/esprima/wiki/ContributionGuide">contribution guide</a>
|
||||||
|
for further info.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sidebar">
|
||||||
|
<h3>Useful demos</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="demo/parse.html">Code parser</a></li>
|
||||||
|
<li><a href="demo/precedence.html">Operator precedence</a></li>
|
||||||
|
<li><a href="demo/collector.html">Regex collector</a></li>
|
||||||
|
<li><a href="demo/functiontrace.html">Function tracing</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Harness tests</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="test/index.html">Unit tests</a></li>
|
||||||
|
<li><a href="test/compat.html">Compatibility tests</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Need for speed</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="test/benchmarks.html">Benchmarks suite</a></li>
|
||||||
|
<li><a href="test/compare.html">Speed comparison</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br clear="all"/>
|
||||||
|
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="http://github.com/ariya/esprima"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://a248.e.akamai.net/assets.github.com/img/e6bef7a091f5f3138b8cd40bc3e114258dd68ddf/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub"></a>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
node_modules/esprima/package.json
generated
vendored
Normal file
31
node_modules/esprima/package.json
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "esprima",
|
||||||
|
"description": "ECMAScript parsing infrastructure for multipurpose analysis",
|
||||||
|
"homepage": "http://esprima.org",
|
||||||
|
"main": "esprima.js",
|
||||||
|
"bin": {
|
||||||
|
"esparse": "./bin/esparse.js"
|
||||||
|
},
|
||||||
|
"version": "0.9.8",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
},
|
||||||
|
"maintainers": [{
|
||||||
|
"name": "Ariya Hidayat",
|
||||||
|
"email": "ariya.hidayat@gmail.com",
|
||||||
|
"web": "http://ariya.ofilabs.com"
|
||||||
|
}],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://github.com/ariya/esprima.git"
|
||||||
|
},
|
||||||
|
"licenses": [{
|
||||||
|
"type": "BSD",
|
||||||
|
"url": "http://github.com/ariya/esprima/raw/master/LICENSE.BSD"
|
||||||
|
}],
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/run.js",
|
||||||
|
"benchmark": "node test/benchmarks.js",
|
||||||
|
"benchmark-quick": "node test/benchmarks.js quick"
|
||||||
|
}
|
||||||
|
}
|
646
node_modules/esprima/test/3rdparty/Tokenizer.js
generated
vendored
Normal file
646
node_modules/esprima/test/3rdparty/Tokenizer.js
generated
vendored
Normal file
@ -0,0 +1,646 @@
|
|||||||
|
if (typeof exports !== 'undefined') {
|
||||||
|
var window = {Unicode: require('./unicodecategories').Unicode};
|
||||||
|
exports.Tokenizer = Tokenizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tokenizer for JavaScript / ECMAScript 5
|
||||||
|
* (c) Peter van der Zee, qfox.nl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} inp
|
||||||
|
*/
|
||||||
|
function Tokenizer(inp){
|
||||||
|
this.inp = inp||'';
|
||||||
|
// replace all other line terminators with \n (leave \r\n in tact though). we should probably remove the shadowInp when finished...
|
||||||
|
// only replace \r if it is not followed by a \n else \r\n would become \n\n causing a double newline where it is just a single
|
||||||
|
this.shadowInp = (inp||'').replace(Tokenizer.regexNormalizeNewlines, '\n');
|
||||||
|
this.pos = 0;
|
||||||
|
this.line = 0;
|
||||||
|
this.column = 0;
|
||||||
|
this.cache = {};
|
||||||
|
|
||||||
|
this.errorStack = [];
|
||||||
|
|
||||||
|
this.wtree = [];
|
||||||
|
this.btree = [];
|
||||||
|
|
||||||
|
// this.regexWhiteSpace = Tokenizer.regexWhiteSpace;
|
||||||
|
this.regexLineTerminator = Tokenizer.regexLineTerminator; // used in fallback
|
||||||
|
this.regexAsciiIdentifier = Tokenizer.regexAsciiIdentifier;
|
||||||
|
this.hashAsciiIdentifier = Tokenizer.hashAsciiIdentifier;
|
||||||
|
// this.regexHex = Tokenizer.regexHex;
|
||||||
|
this.hashHex = Tokenizer.hashHex
|
||||||
|
this.regexUnicodeEscape = Tokenizer.regexUnicodeEscape;
|
||||||
|
this.regexIdentifierStop = Tokenizer.regexIdentifierStop;
|
||||||
|
this.hashIdentifierStop = Tokenizer.hashIdentifierStop;
|
||||||
|
// this.regexPunctuators = Tokenizer.regexPunctuators;
|
||||||
|
this.regexNumber = Tokenizer.regexNumber;
|
||||||
|
this.regexNewline = Tokenizer.regexNewline;
|
||||||
|
|
||||||
|
this.regexBig = Tokenizer.regexBig;
|
||||||
|
this.regexBigAlt = Tokenizer.regexBigAlt;
|
||||||
|
|
||||||
|
this.tokenCount = 0;
|
||||||
|
this.tokenCountNoWhite = 0;
|
||||||
|
|
||||||
|
this.Unicode = window.Unicode;
|
||||||
|
|
||||||
|
// if the Parser throws an error. it will set this property to the next match
|
||||||
|
// at the time of the error (which was not what it was expecting at that point)
|
||||||
|
// and pass on an "error" match. the error should be scooped on the stack and
|
||||||
|
// this property should be returned, without looking at the input...
|
||||||
|
this.errorEscape = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Tokenizer.prototype = {
|
||||||
|
inp:null,
|
||||||
|
shadowInp:null,
|
||||||
|
pos:null,
|
||||||
|
line:null,
|
||||||
|
column:null,
|
||||||
|
cache:null,
|
||||||
|
errorStack:null,
|
||||||
|
|
||||||
|
wtree: null, // contains whitespace (spaces, comments, newlines)
|
||||||
|
btree: null, // does not contain any whitespace tokens.
|
||||||
|
|
||||||
|
regexLineTerminator:null,
|
||||||
|
regexAsciiIdentifier:null,
|
||||||
|
hashAsciiIdentifier:null,
|
||||||
|
hashHex:null,
|
||||||
|
regexUnicodeEscape:null,
|
||||||
|
regexIdentifierStop:null,
|
||||||
|
hashIdentifierStop:null,
|
||||||
|
regexNumber:null,
|
||||||
|
regexNewline:null,
|
||||||
|
regexBig:null,
|
||||||
|
regexBigAlt:null,
|
||||||
|
tokenCount:null,
|
||||||
|
tokenCountNoWhite:null,
|
||||||
|
|
||||||
|
Unicode:null,
|
||||||
|
|
||||||
|
// storeCurrentAndFetchNextToken(bool, false, false true) to get just one token
|
||||||
|
storeCurrentAndFetchNextToken: function(noRegex, returnValue, stack, _dontStore){
|
||||||
|
var regex = !noRegex; // TOFIX :)
|
||||||
|
var pos = this.pos;
|
||||||
|
var inp = this.inp;
|
||||||
|
var shadowInp = this.shadowInp;
|
||||||
|
var matchedNewline = false;
|
||||||
|
do {
|
||||||
|
if (!_dontStore) {
|
||||||
|
++this.tokenCount;
|
||||||
|
stack.push(returnValue);
|
||||||
|
// did the parent Parser throw up?
|
||||||
|
if (this.errorEscape) {
|
||||||
|
returnValue = this.errorEscape;
|
||||||
|
this.errorEscape = null;
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_dontStore = false;
|
||||||
|
|
||||||
|
if (pos >= inp.length) {
|
||||||
|
returnValue = {start:inp.length,stop:inp.length,name:12/*EOF*/};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var returnValue = null;
|
||||||
|
|
||||||
|
var start = pos;
|
||||||
|
var chr = inp[pos];
|
||||||
|
|
||||||
|
// 1 ws 2 lt 3 scmt 4 mcmt 5/6 str 7 nr 8 rx 9 punc
|
||||||
|
//if (true) {
|
||||||
|
// substring method (I think this is faster..)
|
||||||
|
var part2 = inp.substring(pos,pos+4);
|
||||||
|
var part = this.regexBig.exec(part2);
|
||||||
|
//} else {
|
||||||
|
// // non-substring method (lastIndex)
|
||||||
|
// // this method does not need a substring to apply it
|
||||||
|
// this.regexBigAlt.lastIndex = pos;
|
||||||
|
// var part = this.regexBigAlt.exec(inp);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (part[1]) { //this.regexWhiteSpace.test(chr)) { // SP, TAB, VT, FF, NBSP, BOM (, TOFIX: USP)
|
||||||
|
++pos;
|
||||||
|
returnValue = {start:start,stop:pos,name:9/*WHITE_SPACE*/,line:this.line,col:this.column,isWhite:true};
|
||||||
|
++this.column;
|
||||||
|
} else if (part[2]) { //this.regexLineTerminator.test(chr)) { // LF, CR, LS, PS
|
||||||
|
var end = pos+1;
|
||||||
|
if (chr=='\r' && inp[pos+1] == '\n') ++end; // support crlf=>lf
|
||||||
|
returnValue = {start:pos,stop:end,name:10/*LINETERMINATOR*/,line:this.line,col:this.column,isWhite:true};
|
||||||
|
pos = end;
|
||||||
|
// mark newlines for ASI
|
||||||
|
matchedNewline = true;
|
||||||
|
++this.line;
|
||||||
|
this.column = 0;
|
||||||
|
returnValue.hasNewline = 1;
|
||||||
|
} else if (part[3]) { //chr == '/' && inp[pos+1] == '/') {
|
||||||
|
pos = shadowInp.indexOf('\n',pos);
|
||||||
|
if (pos == -1) pos = inp.length;
|
||||||
|
returnValue = {start:start,stop:pos,name:7/*COMMENT_SINGLE*/,line:this.line,col:this.column,isComment:true,isWhite:true};
|
||||||
|
this.column = returnValue.stop;
|
||||||
|
} else if (part[4]) { //chr == '/' && inp[pos+1] == '*') {
|
||||||
|
var newpos = inp.indexOf('*/',pos);
|
||||||
|
if (newpos == -1) {
|
||||||
|
newpos = shadowInp.indexOf('\n', pos);
|
||||||
|
if (newpos < 0) pos += 2;
|
||||||
|
else pos = newpos;
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,value:inp.substring(start, pos),line:this.line,col:this.column,isComment:true,isWhite:true,tokenError:true,error:Tokenizer.Error.UnterminatedMultiLineComment};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
pos = newpos+2;
|
||||||
|
returnValue = {start:start,stop:pos,name:8/*COMMENT_MULTI*/,value:inp.substring(start, pos),line:this.line,col:this.column,isComment:true,isWhite:true};
|
||||||
|
|
||||||
|
// multi line comments are also reason for asi, but only if they contain at least one newline (use shadow input, because all line terminators would be valid...)
|
||||||
|
var shadowValue = shadowInp.substring(start, pos);
|
||||||
|
var i = 0, hasNewline = 0;
|
||||||
|
while (i < (i = shadowValue.indexOf('\n', i+1))) {
|
||||||
|
++hasNewline;
|
||||||
|
}
|
||||||
|
if (hasNewline) {
|
||||||
|
matchedNewline = true;
|
||||||
|
returnValue.hasNewline = hasNewline;
|
||||||
|
this.line += hasNewline;
|
||||||
|
this.column = 0;
|
||||||
|
} else {
|
||||||
|
this.column = returnValue.stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (part[5]) { //chr == "'") {
|
||||||
|
// old method
|
||||||
|
//console.log("old method");
|
||||||
|
|
||||||
|
var hasNewline = 0;
|
||||||
|
do {
|
||||||
|
// process escaped characters
|
||||||
|
while (pos < inp.length && inp[++pos] == '\\') {
|
||||||
|
if (shadowInp[pos+1] == '\n') ++hasNewline;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (this.regexLineTerminator.test(inp[pos])) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,value:inp.substring(start, pos),isString:true,tokenError:true,error:Tokenizer.Error.UnterminatedDoubleStringNewline};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (pos < inp.length && inp[pos] != "'");
|
||||||
|
if (returnValue) {} // error
|
||||||
|
else if (inp[pos] != "'") {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,value:inp.substring(start, pos),isString:true,tokenError:true,error:Tokenizer.Error.UnterminatedDoubleStringOther};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
++pos;
|
||||||
|
returnValue = {start:start,stop:pos,name:5/*STRING_SINGLE*/,isPrimitive:true,isString:true};
|
||||||
|
if (hasNewline) {
|
||||||
|
returnValue.hasNewline = hasNewline;
|
||||||
|
this.line += hasNewline;
|
||||||
|
this.column = 0;
|
||||||
|
} else {
|
||||||
|
this.column += (pos-start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (part[6]) { //chr == '"') {
|
||||||
|
var hasNewline = 0;
|
||||||
|
// TODO: something like this: var regexmatch = /([^\']|$)+/.match();
|
||||||
|
do {
|
||||||
|
// process escaped chars
|
||||||
|
while (pos < inp.length && inp[++pos] == '\\') {
|
||||||
|
if (shadowInp[pos+1] == '\n') ++hasNewline;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (this.regexLineTerminator.test(inp[pos])) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,value:inp.substring(start, pos),isString:true,tokenError:true,error:Tokenizer.Error.UnterminatedSingleStringNewline};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (pos < inp.length && inp[pos] != '"');
|
||||||
|
if (returnValue) {}
|
||||||
|
else if (inp[pos] != '"') {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,value:inp.substring(start, pos),isString:true,tokenError:true,error:Tokenizer.Error.UnterminatedSingleStringOther};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
++pos;
|
||||||
|
returnValue = {start:start,stop:pos,name:6/*STRING_DOUBLE*/,isPrimitive:true,isString:true};
|
||||||
|
if (hasNewline) {
|
||||||
|
returnValue.hasNewline = hasNewline;
|
||||||
|
this.line += hasNewline;
|
||||||
|
this.column = 0;
|
||||||
|
} else {
|
||||||
|
this.column += (pos-start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (part[7]) { //(chr >= '0' && chr <= '9') || (chr == '.' && inp[pos+1] >= '0' && inp[pos+1] <= '9')) {
|
||||||
|
var nextPart = inp.substring(pos, pos+30);
|
||||||
|
var match = nextPart.match(this.regexNumber);
|
||||||
|
if (match[2]) { // decimal
|
||||||
|
var value = match[2];
|
||||||
|
var parsingOctal = value[0] == '0' && value[1] && value[1] != 'e' && value[1] != 'E' && value[1] != '.';
|
||||||
|
if (parsingOctal) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,isNumber:true,isOctal:true,tokenError:true,error:Tokenizer.Error.IllegalOctalEscape,value:value};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
returnValue = {start:start,stop:start+value.length,name:4/*NUMERIC_DEC*/,isPrimitive:true,isNumber:true,value:value};
|
||||||
|
}
|
||||||
|
} else if (match[1]) { // hex
|
||||||
|
var value = match[1];
|
||||||
|
returnValue = {start:start,stop:start+value.length,name:3/*NUMERIC_HEX*/,isPrimitive:true,isNumber:true,value:value};
|
||||||
|
} else {
|
||||||
|
throw 'unexpected parser errror... regex fail :(';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.length < 300) {
|
||||||
|
pos += value.length;
|
||||||
|
} else {
|
||||||
|
// old method of parsing numbers. only used for extremely long number literals (300+ chars).
|
||||||
|
// this method does not require substringing... just memory :)
|
||||||
|
var tmpReturnValue = this.oldNumberParser(pos, chr, inp, returnValue, start, Tokenizer);
|
||||||
|
pos = tmpReturnValue[0];
|
||||||
|
returnValue = tmpReturnValue[1];
|
||||||
|
}
|
||||||
|
} else if (regex && part[8]) { //chr == '/') { // regex cannot start with /* (would be multiline comment, and not make sense anyways). but if it was /* then an earlier if would have eated it. so we only check for /
|
||||||
|
var twinfo = []; // matching {[( info
|
||||||
|
var found = false;
|
||||||
|
var parens = [];
|
||||||
|
var nonLethalError = null;
|
||||||
|
while (++pos < inp.length) {
|
||||||
|
chr = shadowInp[pos];
|
||||||
|
// parse RegularExpressionChar
|
||||||
|
if (chr == '\n') {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,tokenError:true,errorHasContent:true,error:Tokenizer.Error.UnterminatedRegularExpressionNewline};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
break; // fail
|
||||||
|
} else if (chr == '/') {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
} else if (chr == '?' || chr == '*' || chr == '+') {
|
||||||
|
nonLethalError = Tokenizer.Error.NothingToRepeat;
|
||||||
|
} else if (chr == '^') {
|
||||||
|
if (
|
||||||
|
inp[pos-1] != '/' &&
|
||||||
|
inp[pos-1] != '|' &&
|
||||||
|
inp[pos-1] != '(' &&
|
||||||
|
!(inp[pos-3] == '(' && inp[pos-2] == '?' && (inp[pos-1] == ':' || inp[pos-1] == '!' || inp[pos-1] == '='))
|
||||||
|
) {
|
||||||
|
nonLethalError = Tokenizer.Error.StartOfMatchShouldBeAtStart;
|
||||||
|
}
|
||||||
|
} else if (chr == '$') {
|
||||||
|
if (inp[pos+1] != '/' && inp[pos+1] != '|' && inp[pos+1] != ')') nonLethalError = Tokenizer.Error.DollarShouldBeEnd;
|
||||||
|
} else if (chr == '}') {
|
||||||
|
nonLethalError = Tokenizer.Error.MissingOpeningCurly;
|
||||||
|
} else { // it's a "character" (can be group or class), something to match
|
||||||
|
// match parenthesis
|
||||||
|
if (chr == '(') {
|
||||||
|
parens.push(pos-start);
|
||||||
|
} else if (chr == ')') {
|
||||||
|
if (parens.length == 0) {
|
||||||
|
nonLethalError = {start:start,stop:pos,name:14/*error*/,tokenError:true,error:Tokenizer.Error.RegexNoOpenGroups};
|
||||||
|
} else {
|
||||||
|
var twin = parens.pop();
|
||||||
|
var now = pos-start;
|
||||||
|
twinfo[twin] = now;
|
||||||
|
twinfo[now] = twin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// first process character class
|
||||||
|
if (chr == '[') {
|
||||||
|
var before = pos-start;
|
||||||
|
while (++pos < inp.length && shadowInp[pos] != '\n' && inp[pos] != ']') {
|
||||||
|
// only newline is not allowed in class range
|
||||||
|
// anything else can be escaped, most of it does not have to be escaped...
|
||||||
|
if (inp[pos] == '\\') {
|
||||||
|
if (shadowInp[pos+1] == '\n') break;
|
||||||
|
else ++pos; // skip next char. (mainly prohibits ] to be picked up as closing the group...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inp[pos] != ']') {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,tokenError:true,error:Tokenizer.Error.ClosingClassRangeNotFound};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
var after = pos-start;
|
||||||
|
twinfo[before] = after;
|
||||||
|
twinfo[after] = before;
|
||||||
|
}
|
||||||
|
} else if (chr == '\\' && shadowInp[pos+1] != '\n') {
|
||||||
|
// is ok anywhere in the regex (match next char literally, regardless of its otherwise special meaning)
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now process repeaters (+, ? and *)
|
||||||
|
|
||||||
|
// non-collecting group (?:...) and positive (?=...) or negative (?!...) lookahead
|
||||||
|
if (chr == '(') {
|
||||||
|
if (inp[pos+1] == '?' && (inp[pos+2] == ':' || inp[pos+2] == '=' || inp[pos+2] == '!')) {
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// matching "char"
|
||||||
|
else if (inp[pos+1] == '?') ++pos;
|
||||||
|
else if (inp[pos+1] == '*' || inp[pos+1] == '+') {
|
||||||
|
++pos;
|
||||||
|
if (inp[pos+1] == '?') ++pos; // non-greedy match
|
||||||
|
} else if (inp[pos+1] == '{') {
|
||||||
|
pos += 1;
|
||||||
|
var before = pos-start;
|
||||||
|
// quantifier:
|
||||||
|
// - {n}
|
||||||
|
// - {n,}
|
||||||
|
// - {n,m}
|
||||||
|
if (!/[0-9]/.test(inp[pos+1])) {
|
||||||
|
nonLethalError = Tokenizer.Error.QuantifierRequiresNumber;
|
||||||
|
}
|
||||||
|
while (++pos < inp.length && /[0-9]/.test(inp[pos+1]));
|
||||||
|
if (inp[pos+1] == ',') {
|
||||||
|
++pos;
|
||||||
|
while (pos < inp.length && /[0-9]/.test(inp[pos+1])) ++pos;
|
||||||
|
}
|
||||||
|
if (inp[pos+1] != '}') {
|
||||||
|
nonLethalError = Tokenizer.Error.QuantifierRequiresClosingCurly;
|
||||||
|
} else {
|
||||||
|
++pos;
|
||||||
|
var after = pos-start;
|
||||||
|
twinfo[before] = after;
|
||||||
|
twinfo[after] = before;
|
||||||
|
if (inp[pos+1] == '?') ++pos; // non-greedy match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if found=false, fail right now. otherwise try to parse an identifiername (that's all RegularExpressionFlags is..., but it's constructed in a stupid fashion)
|
||||||
|
if (!found || returnValue) {
|
||||||
|
if (!returnValue) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,tokenError:true,error:Tokenizer.Error.UnterminatedRegularExpressionOther};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// this is the identifier scanner, for now
|
||||||
|
do ++pos;
|
||||||
|
while (pos < inp.length && this.hashAsciiIdentifier[inp[pos]]); /*this.regexAsciiIdentifier.test(inp[pos])*/
|
||||||
|
|
||||||
|
if (parens.length) {
|
||||||
|
// nope, this is still an error, there was at least one paren that did not have a matching twin
|
||||||
|
if (parens.length > 0) returnValue = {start:start,stop:pos,name:14/*error*/,tokenError:true,error:Tokenizer.Error.RegexOpenGroup};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else if (nonLethalError) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,errorHasContent:true,tokenError:true,error:nonLethalError};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
returnValue = {start:start,stop:pos,name:1/*REG_EX*/,isPrimitive:true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnValue.twinfo = twinfo;
|
||||||
|
} else {
|
||||||
|
// note: operators need to be ordered from longest to smallest. regex will take care of the rest.
|
||||||
|
// no need to worry about div vs regex. if looking for regex, earlier if will have eaten it
|
||||||
|
//var result = this.regexPunctuators.exec(inp.substring(pos,pos+4));
|
||||||
|
|
||||||
|
// note: due to the regex, the single forward slash might be caught by an earlier part of the regex. so check for that.
|
||||||
|
var result = part[8] || part[9];
|
||||||
|
if (result) {
|
||||||
|
//result = result[1];
|
||||||
|
returnValue = {start:pos,stop:pos+=result.length,name:11/*PUNCTUATOR*/,value:result};
|
||||||
|
} else {
|
||||||
|
var found = false;
|
||||||
|
// identifiers cannot start with a number. but if the leading string would be a number, another if would have eaten it already for numeric literal :)
|
||||||
|
while (pos < inp.length) {
|
||||||
|
var c = inp[pos];
|
||||||
|
|
||||||
|
if (this.hashAsciiIdentifier[c]) ++pos; //if (this.regexAsciiIdentifier.test(c)) ++pos;
|
||||||
|
else if (c == '\\' && this.regexUnicodeEscape.test(inp.substring(pos,pos+6))) pos += 6; // this is like a \uxxxx
|
||||||
|
// ok, now test unicode ranges...
|
||||||
|
// basically this hardly ever happens so there's little risk of this hitting performance
|
||||||
|
// however, if you do happen to have used them, it's not a problem. the parser will support it :)
|
||||||
|
else if (this.Unicode) { // the unicode is optional.
|
||||||
|
// these chars may not be part of identifier. i want to try to prevent running the unicode regexes here...
|
||||||
|
if (this.hashIdentifierStop[c] /*this.regexIdentifierStop.test(c)*/) break;
|
||||||
|
// for most scripts, the code wont reach here. which is good, because this is going to be relatively slow :)
|
||||||
|
var Unicode = this.Unicode; // cache
|
||||||
|
if (!(
|
||||||
|
// these may all occur in an identifier... (pure a specification compliance thing :)
|
||||||
|
Unicode.Lu.test(c) || Unicode.Ll.test(c) || Unicode.Lt.test(c) || Unicode.Lm.test(c) ||
|
||||||
|
Unicode.Lo.test(c) || Unicode.Nl.test(c) || Unicode.Mn.test(c) || Unicode.Mc.test(c) ||
|
||||||
|
Unicode.Nd.test(c) || Unicode.Pc.test(c) || Unicode.sp.test(c)
|
||||||
|
)) break; // end of match.
|
||||||
|
// passed, next char
|
||||||
|
++pos;
|
||||||
|
} else break; // end of match.
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
returnValue = {start:start,stop:pos,name:2/*IDENTIFIER*/,value:inp.substring(start,pos)};
|
||||||
|
if (returnValue.value == 'undefined' || returnValue.value == 'null' || returnValue.value == 'true' || returnValue.value == 'false') returnValue.isPrimitive = true;
|
||||||
|
} else {
|
||||||
|
if (inp[pos] == '`') {
|
||||||
|
returnValue = {start:start,stop:pos+1,name:14/*error*/,tokenError:true,error:Tokenizer.Error.BacktickNotSupported};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else if (inp[pos] == '\\') {
|
||||||
|
if (inp[pos+1] == 'u') {
|
||||||
|
returnValue = {start:start,stop:pos+1,name:14/*error*/,tokenError:true,error:Tokenizer.Error.InvalidUnicodeEscape};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
} else {
|
||||||
|
returnValue = {start:start,stop:pos+1,name:14/*error*/,tokenError:true,error:Tokenizer.Error.InvalidBackslash};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
returnValue = {start:start,stop:pos+1,name:14/*error*/,tokenError:true,error:Tokenizer.Error.Unknown,value:c};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
// try to skip this char. it's not going anywhere.
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnValue) {
|
||||||
|
// note that ASI's are slipstreamed in here from the parser since the tokenizer cant determine that
|
||||||
|
// if this part ever changes, make sure you change that too :)
|
||||||
|
returnValue.tokposw = this.wtree.length;
|
||||||
|
this.wtree.push(returnValue);
|
||||||
|
if (!returnValue.isWhite) {
|
||||||
|
returnValue.tokposb = this.btree.length;
|
||||||
|
this.btree.push(returnValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} while (stack && returnValue && returnValue.isWhite); // WHITE_SPACE LINETERMINATOR COMMENT_SINGLE COMMENT_MULTI
|
||||||
|
++this.tokenCountNoWhite;
|
||||||
|
|
||||||
|
this.pos = pos;
|
||||||
|
|
||||||
|
if (matchedNewline) returnValue.newline = true;
|
||||||
|
return returnValue;
|
||||||
|
},
|
||||||
|
addTokenToStreamBefore: function(token, match){
|
||||||
|
var wtree = this.wtree;
|
||||||
|
var btree = this.btree;
|
||||||
|
if (match.name == 12/*asi*/) {
|
||||||
|
token.tokposw = wtree.length;
|
||||||
|
wtree.push(token);
|
||||||
|
token.tokposb = btree.length;
|
||||||
|
btree.push(token);
|
||||||
|
} else {
|
||||||
|
token.tokposw = match.tokposw;
|
||||||
|
wtree[token.tokposw] = token;
|
||||||
|
match.tokposw += 1;
|
||||||
|
wtree[match.tokposw] = match;
|
||||||
|
|
||||||
|
if (match.tokposb) {
|
||||||
|
token.tokposb = match.tokposb;
|
||||||
|
btree[token.tokposb] = token;
|
||||||
|
match.tokposb += 1;
|
||||||
|
btree[match.tokposb] = match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
oldNumberParser: function(pos, chr, inp, returnValue, start, Tokenizer){
|
||||||
|
++pos;
|
||||||
|
// either: 0x 0X 0 .3
|
||||||
|
if (chr == '0' && (inp[pos] == 'x' || inp[pos] == 'X')) {
|
||||||
|
// parsing hex
|
||||||
|
while (++pos < inp.length && this.hashHex[inp[pos]]); // this.regexHex.test(inp[pos]));
|
||||||
|
returnValue = {start:start,stop:pos,name:3/*NUMERIC_HEX*/,isPrimitive:true,isNumber:true};
|
||||||
|
} else {
|
||||||
|
var parsingOctal = chr == '0' && inp[pos] >= '0' && inp[pos] <= '9';
|
||||||
|
// parsing dec
|
||||||
|
if (chr != '.') { // integer part
|
||||||
|
while (pos < inp.length && inp[pos] >= '0' && inp[pos] <= '9') ++pos;
|
||||||
|
if (inp[pos] == '.') ++pos;
|
||||||
|
}
|
||||||
|
// decimal part
|
||||||
|
while (pos < inp.length && inp[pos] >= '0' && inp[pos] <= '9') ++pos;
|
||||||
|
// exponent part
|
||||||
|
if (inp[pos] == 'e' || inp[pos] == 'E') {
|
||||||
|
if (inp[++pos] == '+' || inp[pos] == '-') ++pos;
|
||||||
|
var expPosBak = pos;
|
||||||
|
while (pos < inp.length && inp[pos] >= '0' && inp[pos] <= '9') ++pos;
|
||||||
|
if (expPosBak == pos) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,tokenError:true,error:Tokenizer.Error.NumberExponentRequiresDigits};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (returnValue.name != 14/*error*/) {
|
||||||
|
if (parsingOctal) {
|
||||||
|
returnValue = {start:start,stop:pos,name:14/*error*/,isNumber:true,isOctal:true,tokenError:true,error:Tokenizer.Error.IllegalOctalEscape};
|
||||||
|
this.errorStack.push(returnValue);
|
||||||
|
console.log("foo")
|
||||||
|
} else {
|
||||||
|
returnValue = {start:start,stop:pos,name:4/*NUMERIC_DEC*/,isPrimitive:true,isNumber:true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [pos, returnValue];
|
||||||
|
},
|
||||||
|
tokens: function(arrx){
|
||||||
|
arrx = arrx || [];
|
||||||
|
var n = 0;
|
||||||
|
var last;
|
||||||
|
var stack = [];
|
||||||
|
while ((last = this.storeCurrentAndFetchNextToken(!arrx[n++], false, false, true)) && last.name != 12/*EOF*/) stack.push(last);
|
||||||
|
return stack;
|
||||||
|
},
|
||||||
|
fixValues: function(){
|
||||||
|
this.wtree.forEach(function(t){
|
||||||
|
if (!t.value) t.value = this.inp.substring(t.start, t.stop);
|
||||||
|
},this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//#ifdef TEST_SUITE
|
||||||
|
Tokenizer.escape = function(s){
|
||||||
|
return s.replace(/\n/g,'\\n').replace(/\t/g,'\\t').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\uFFFF/g, '\\uFFFF').replace(/\s/g, function(s){
|
||||||
|
// replace whitespace as is...
|
||||||
|
var ord = s.charCodeAt(0).toString(16);
|
||||||
|
switch (ord.length) {
|
||||||
|
case 1: ord = '000'+ord; break;
|
||||||
|
case 2: ord = '00'+ord; break;
|
||||||
|
case 3: ord = '0'+ord; break;
|
||||||
|
}
|
||||||
|
return '\\u'+ord;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Tokenizer.testSuite = function(arr){
|
||||||
|
var out = document.createElement('pre');
|
||||||
|
document.body.appendChild(out);
|
||||||
|
var debug = function(){
|
||||||
|
var f = document.createElement('div');
|
||||||
|
f.innerHTML = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
out.appendChild(f);
|
||||||
|
return arguments[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
debug("Running test suite...",arr.length,"tests");
|
||||||
|
debug(' ');
|
||||||
|
var start = +new Date;
|
||||||
|
var ok = 0;
|
||||||
|
var fail = 0;
|
||||||
|
for (var i=0; i<arr.length; ++i) {
|
||||||
|
var test = arr[i], result;
|
||||||
|
var input = test[0];
|
||||||
|
var outputLen = test[1].length ? test[1][0] : test[1];
|
||||||
|
var regexHints = test[3] ? test[2] : null; // if flags, then len=4
|
||||||
|
var desc = test[3] || test[2];
|
||||||
|
|
||||||
|
var result = new Tokenizer(input).tokens(regexHints); // regexHints can be null, that's ok
|
||||||
|
if (result.length == outputLen) {
|
||||||
|
debug('<span class="green">Test '+i+' ok:</span>',desc);
|
||||||
|
++ok;
|
||||||
|
} else {
|
||||||
|
debug('<b class="red">Test failed:</span>',desc,'(found',result.length,'expected',outputLen+')'),console.log(desc, result);
|
||||||
|
++fail;
|
||||||
|
}
|
||||||
|
debug('<b>'+Tokenizer.escape(input)+'</b>');
|
||||||
|
debug('<br/>');
|
||||||
|
}
|
||||||
|
debug("Tokenizer test suite finished ("+(+new Date - start)+' ms). ok:'+ok+', fail:'+fail);
|
||||||
|
};
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
Tokenizer.regexWhiteSpace = /[ \t\u000B\u000C\u00A0\uFFFF]/;
|
||||||
|
Tokenizer.regexLineTerminator = /[\u000A\u000D\u2028\u2029]/;
|
||||||
|
Tokenizer.regexAsciiIdentifier = /[a-zA-Z0-9\$_]/;
|
||||||
|
Tokenizer.hashAsciiIdentifier = {_:1,$:1,a:1,b:1,c:1,d:1,e:1,f:1,g:1,h:1,i:1,j:1,k:1,l:1,m:1,n:1,o:1,p:1,q:1,r:1,s:1,t:1,u:1,v:1,w:1,x:1,y:1,z:1,A:1,B:1,C:1,D:1,E:1,F:1,G:1,H:1,I:1,J:1,K:1,L:1,M:1,N:1,O:1,P:1,Q:1,R:1,S:1,T:1,U:1,V:1,W:1,X:1,Y:1,Z:1,0:1,1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1};
|
||||||
|
Tokenizer.regexHex = /[0-9A-Fa-f]/;
|
||||||
|
Tokenizer.hashHex = {0:1,1:1,2:1,3:1,4:1,5:1,6:1,7:1,8:1,9:1,a:1,b:1,c:1,d:1,e:1,f:1,A:1,B:1,C:1,D:1,E:1,F:1};
|
||||||
|
Tokenizer.regexUnicodeEscape = /u[0-9A-Fa-f]{4}/; // the \ is already checked at usage...
|
||||||
|
Tokenizer.regexIdentifierStop = /[\>\=\!\|\<\+\-\&\*\%\^\/\{\}\(\)\[\]\.\;\,\~\?\:\ \t\n\\\'\"]/;
|
||||||
|
Tokenizer.hashIdentifierStop = {'>':1,'=':1,'!':1,'|':1,'<':1,'+':1,'-':1,'&':1,'*':1,'%':1,'^':1,'/':1,'{':1,'}':1,'(':1,')':1,'[':1,']':1,'.':1,';':1,',':1,'~':1,'?':1,':':1,'\\':1,'\'':1,'"':1,' ':1,'\t':1,'\n':1};
|
||||||
|
Tokenizer.regexNewline = /\n/g;
|
||||||
|
//Tokenizer.regexPunctuators = /^(>>>=|===|!==|>>>|<<=|>>=|<=|>=|==|!=|\+\+|--|<<|>>|\&\&|\|\||\+=|-=|\*=|%=|\&=|\|=|\^=|\/=|\{|\}|\(|\)|\[|\]|\.|;|,|<|>|\+|-|\*|%|\||\&|\||\^|!|~|\?|:|=|\/)/;
|
||||||
|
Tokenizer.Unidocde = window.Unicode;
|
||||||
|
Tokenizer.regexNumber = /^(?:(0[xX][0-9A-Fa-f]+)|((?:(?:(?:(?:[0-9]+)(?:\.[0-9]*)?))|(?:\.[0-9]+))(?:[eE][-+]?[0-9]{1,})?))/;
|
||||||
|
Tokenizer.regexNormalizeNewlines = /(\u000D[^\u000A])|[\u2028\u2029]/;
|
||||||
|
|
||||||
|
// 1 ws 2 lt 3 scmt 4 mcmt 5/6 str 7 nr 8 rx 9 punc
|
||||||
|
Tokenizer.regexBig = /^([ \t\u000B\u000C\u00A0\uFFFF])?([\u000A\u000D\u2028\u2029])?(\/\/)?(\/\*)?(')?(")?(\.?[0-9])?(?:(\/)[^=])?(>>>=|===|!==|>>>|<<=|>>=|<=|>=|==|!=|\+\+|--|<<|>>|\&\&|\|\||\+=|-=|\*=|%=|\&=|\|=|\^=|\/=|\{|\}|\(|\)|\[|\]|\.|;|,|<|>|\+|-|\*|%|\||\&|\||\^|!|~|\?|:|=|\/)?/;
|
||||||
|
Tokenizer.regexBigAlt = /([ \t\u000B\u000C\u00A0\uFFFF])?([\u000A\u000D\u2028\u2029])?(\/\/)?(\/\*)?(')?(")?(\.?[0-9])?(?:(\/)[^=])?(>>>=|===|!==|>>>|<<=|>>=|<=|>=|==|!=|\+\+|--|<<|>>|\&\&|\|\||\+=|-=|\*=|%=|\&=|\|=|\^=|\/=|\{|\}|\(|\)|\[|\]|\.|;|,|<|>|\+|-|\*|%|\||\&|\||\^|!|~|\?|:|=|\/)?/g;
|
||||||
|
|
||||||
|
Tokenizer.Error = {
|
||||||
|
UnterminatedSingleStringNewline: {msg:'Newlines are not allowed in string literals'},
|
||||||
|
UnterminatedSingleStringOther: {msg:'Unterminated single string'},
|
||||||
|
UnterminatedDoubleStringNewline: {msg:'Newlines are not allowed in string literals'},
|
||||||
|
UnterminatedDoubleStringOther: {msg:'Unterminated double string'},
|
||||||
|
UnterminatedRegularExpressionNewline: {msg:'Newlines are not allowed in regular expressions'},
|
||||||
|
NothingToRepeat: {msg:'Used a repeat character (*?+) in a regex without something prior to it to match'},
|
||||||
|
ClosingClassRangeNotFound: {msg: 'Unable to find ] for class range'},
|
||||||
|
RegexOpenGroup: {msg: 'Open group did not find closing parenthesis'},
|
||||||
|
RegexNoOpenGroups: {msg: 'Closing parenthesis found but no group open'},
|
||||||
|
UnterminatedRegularExpressionOther: {msg:'Unterminated regular expression'},
|
||||||
|
UnterminatedMultiLineComment: {msg:'Unterminated multi line comment'},
|
||||||
|
UnexpectedIdentifier: {msg:'Unexpected identifier'},
|
||||||
|
IllegalOctalEscape: {msg:'Octal escapes are not valid'},
|
||||||
|
Unknown: {msg:'Unknown input'}, // if this happens, my parser is bad :(
|
||||||
|
NumberExponentRequiresDigits: {msg:'Numbers with exponents require at least one digit after the `e`'},
|
||||||
|
BacktickNotSupported: {msg:'The backtick is not used in js, maybe you copy/pasted from a fancy site/doc?'},
|
||||||
|
InvalidUnicodeEscape: {msg:'Encountered an invalid unicode escape, must be followed by exactly four hex numbers'},
|
||||||
|
InvalidBackslash: {msg:'Encountered a backslash where it not allowed'},
|
||||||
|
StartOfMatchShouldBeAtStart: {msg: 'The ^ signifies the start of match but was not found at a start'},
|
||||||
|
DollarShouldBeEnd: {msg: 'The $ signifies the stop of match but was not found at a stop'},
|
||||||
|
QuantifierRequiresNumber: {msg:'Quantifier curly requires at least one digit before the comma'},
|
||||||
|
QuantifierRequiresClosingCurly: {msg:'Quantifier curly requires to be closed'},
|
||||||
|
MissingOpeningCurly: {msg:'Encountered closing quantifier curly without seeing an opening curly'}
|
||||||
|
};
|
509
node_modules/esprima/test/3rdparty/XMLHttpRequest.js
generated
vendored
Normal file
509
node_modules/esprima/test/3rdparty/XMLHttpRequest.js
generated
vendored
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
/**
|
||||||
|
* XMLHttpRequest.js Copyright (C) 2011 Sergey Ilinsky (http://www.ilinsky.com)
|
||||||
|
*
|
||||||
|
* This work is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This work is distributed in the hope that it will be useful,
|
||||||
|
* but without any warranty; without even the implied warranty of
|
||||||
|
* merchantability or fitness for a particular purpose. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
// Save reference to earlier defined object implementation (if any)
|
||||||
|
var oXMLHttpRequest = window.XMLHttpRequest;
|
||||||
|
|
||||||
|
// Define on browser type
|
||||||
|
var bGecko = !!window.controllers;
|
||||||
|
var bIE = window.document.all && !window.opera;
|
||||||
|
var bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
|
||||||
|
|
||||||
|
// Enables "XMLHttpRequest()" call next to "new XMLHttpReques()"
|
||||||
|
function fXMLHttpRequest() {
|
||||||
|
this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
this._listeners = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
function cXMLHttpRequest() {
|
||||||
|
return new fXMLHttpRequest;
|
||||||
|
}
|
||||||
|
cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
|
||||||
|
|
||||||
|
// BUGFIX: Firefox with Firebug installed would break pages if not executed
|
||||||
|
if (bGecko && oXMLHttpRequest.wrapped) {
|
||||||
|
cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
cXMLHttpRequest.UNSENT = 0;
|
||||||
|
cXMLHttpRequest.OPENED = 1;
|
||||||
|
cXMLHttpRequest.HEADERS_RECEIVED = 2;
|
||||||
|
cXMLHttpRequest.LOADING = 3;
|
||||||
|
cXMLHttpRequest.DONE = 4;
|
||||||
|
|
||||||
|
// Public Properties
|
||||||
|
cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;
|
||||||
|
cXMLHttpRequest.prototype.responseText = '';
|
||||||
|
cXMLHttpRequest.prototype.responseXML = null;
|
||||||
|
cXMLHttpRequest.prototype.status = 0;
|
||||||
|
cXMLHttpRequest.prototype.statusText = '';
|
||||||
|
|
||||||
|
// Priority proposal
|
||||||
|
cXMLHttpRequest.prototype.priority = "NORMAL";
|
||||||
|
|
||||||
|
// Instance-level Events Handlers
|
||||||
|
cXMLHttpRequest.prototype.onreadystatechange = null;
|
||||||
|
|
||||||
|
// Class-level Events Handlers
|
||||||
|
cXMLHttpRequest.onreadystatechange = null;
|
||||||
|
cXMLHttpRequest.onopen = null;
|
||||||
|
cXMLHttpRequest.onsend = null;
|
||||||
|
cXMLHttpRequest.onabort = null;
|
||||||
|
|
||||||
|
// Public Methods
|
||||||
|
cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {
|
||||||
|
// Delete headers, required when object is reused
|
||||||
|
delete this._headers;
|
||||||
|
|
||||||
|
// When bAsync parameter value is omitted, use true as default
|
||||||
|
if (arguments.length < 3) {
|
||||||
|
bAsync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
|
||||||
|
this._async = bAsync;
|
||||||
|
|
||||||
|
// Set the onreadystatechange handler
|
||||||
|
var oRequest = this;
|
||||||
|
var nState = this.readyState;
|
||||||
|
var fOnUnload = null;
|
||||||
|
|
||||||
|
// BUGFIX: IE - memory leak on page unload (inter-page leak)
|
||||||
|
if (bIE && bAsync) {
|
||||||
|
fOnUnload = function() {
|
||||||
|
if (nState != cXMLHttpRequest.DONE) {
|
||||||
|
fCleanTransport(oRequest);
|
||||||
|
// Safe to abort here since onreadystatechange handler removed
|
||||||
|
oRequest.abort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.attachEvent("onunload", fOnUnload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add method sniffer
|
||||||
|
if (cXMLHttpRequest.onopen) {
|
||||||
|
cXMLHttpRequest.onopen.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.length > 4) {
|
||||||
|
this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
|
||||||
|
} else if (arguments.length > 3) {
|
||||||
|
this._object.open(sMethod, sUrl, bAsync, sUser);
|
||||||
|
} else {
|
||||||
|
this._object.open(sMethod, sUrl, bAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.readyState = cXMLHttpRequest.OPENED;
|
||||||
|
fReadyStateChange(this);
|
||||||
|
|
||||||
|
this._object.onreadystatechange = function() {
|
||||||
|
if (bGecko && !bAsync) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synchronize state
|
||||||
|
oRequest.readyState = oRequest._object.readyState;
|
||||||
|
fSynchronizeValues(oRequest);
|
||||||
|
|
||||||
|
// BUGFIX: Firefox fires unnecessary DONE when aborting
|
||||||
|
if (oRequest._aborted) {
|
||||||
|
// Reset readyState to UNSENT
|
||||||
|
oRequest.readyState = cXMLHttpRequest.UNSENT;
|
||||||
|
|
||||||
|
// Return now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oRequest.readyState == cXMLHttpRequest.DONE) {
|
||||||
|
// Free up queue
|
||||||
|
delete oRequest._data;
|
||||||
|
|
||||||
|
// Uncomment these lines for bAsync
|
||||||
|
/**
|
||||||
|
* if (bAsync) {
|
||||||
|
* fQueue_remove(oRequest);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
fCleanTransport(oRequest);
|
||||||
|
|
||||||
|
// Uncomment this block if you need a fix for IE cache
|
||||||
|
/**
|
||||||
|
* // BUGFIX: IE - cache issue
|
||||||
|
* if (!oRequest._object.getResponseHeader("Date")) {
|
||||||
|
* // Save object to cache
|
||||||
|
* oRequest._cached = oRequest._object;
|
||||||
|
*
|
||||||
|
* // Instantiate a new transport object
|
||||||
|
* cXMLHttpRequest.call(oRequest);
|
||||||
|
*
|
||||||
|
* // Re-send request
|
||||||
|
* if (sUser) {
|
||||||
|
* if (sPassword) {
|
||||||
|
* oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
|
||||||
|
* } else {
|
||||||
|
* oRequest._object.open(sMethod, sUrl, bAsync);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
|
||||||
|
* // Copy headers set
|
||||||
|
* if (oRequest._headers) {
|
||||||
|
* for (var sHeader in oRequest._headers) {
|
||||||
|
* // Some frameworks prototype objects with functions
|
||||||
|
* if (typeof oRequest._headers[sHeader] == "string") {
|
||||||
|
* oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* oRequest._object.onreadystatechange = function() {
|
||||||
|
* // Synchronize state
|
||||||
|
* oRequest.readyState = oRequest._object.readyState;
|
||||||
|
*
|
||||||
|
* if (oRequest._aborted) {
|
||||||
|
* //
|
||||||
|
* oRequest.readyState = cXMLHttpRequest.UNSENT;
|
||||||
|
*
|
||||||
|
* // Return
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* if (oRequest.readyState == cXMLHttpRequest.DONE) {
|
||||||
|
* // Clean Object
|
||||||
|
* fCleanTransport(oRequest);
|
||||||
|
*
|
||||||
|
* // get cached request
|
||||||
|
* if (oRequest.status == 304) {
|
||||||
|
* oRequest._object = oRequest._cached;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* //
|
||||||
|
* delete oRequest._cached;
|
||||||
|
*
|
||||||
|
* //
|
||||||
|
* fSynchronizeValues(oRequest);
|
||||||
|
*
|
||||||
|
* //
|
||||||
|
* fReadyStateChange(oRequest);
|
||||||
|
*
|
||||||
|
* // BUGFIX: IE - memory leak in interrupted
|
||||||
|
* if (bIE && bAsync) {
|
||||||
|
* window.detachEvent("onunload", fOnUnload);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
* oRequest._object.send(null);
|
||||||
|
*
|
||||||
|
* // Return now - wait until re-sent request is finished
|
||||||
|
* return;
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
// BUGFIX: IE - memory leak in interrupted
|
||||||
|
if (bIE && bAsync) {
|
||||||
|
window.detachEvent("onunload", fOnUnload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
|
||||||
|
if (nState != oRequest.readyState) {
|
||||||
|
fReadyStateChange(oRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
nState = oRequest.readyState;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.send = function(vData) {
|
||||||
|
// Add method sniffer
|
||||||
|
if (cXMLHttpRequest.onsend) {
|
||||||
|
cXMLHttpRequest.onsend.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments.length) {
|
||||||
|
vData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
|
||||||
|
// BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
|
||||||
|
// BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
|
||||||
|
if (vData && vData.nodeType) {
|
||||||
|
vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
|
||||||
|
if (!this._headers["Content-Type"]) {
|
||||||
|
this._object.setRequestHeader("Content-Type", "application/xml");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._data = vData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* // Add to queue
|
||||||
|
* if (this._async) {
|
||||||
|
* fQueue_add(this);
|
||||||
|
* } else { */
|
||||||
|
fXMLHttpRequest_send(this);
|
||||||
|
/**
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.abort = function() {
|
||||||
|
// Add method sniffer
|
||||||
|
if (cXMLHttpRequest.onabort) {
|
||||||
|
cXMLHttpRequest.onabort.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUGFIX: Gecko - unnecessary DONE when aborting
|
||||||
|
if (this.readyState > cXMLHttpRequest.UNSENT) {
|
||||||
|
this._aborted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._object.abort();
|
||||||
|
|
||||||
|
// BUGFIX: IE - memory leak
|
||||||
|
fCleanTransport(this);
|
||||||
|
|
||||||
|
this.readyState = cXMLHttpRequest.UNSENT;
|
||||||
|
|
||||||
|
delete this._data;
|
||||||
|
|
||||||
|
/* if (this._async) {
|
||||||
|
* fQueue_remove(this);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
|
||||||
|
return this._object.getAllResponseHeaders();
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
|
||||||
|
return this._object.getResponseHeader(sName);
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
|
||||||
|
// BUGFIX: IE - cache issue
|
||||||
|
if (!this._headers) {
|
||||||
|
this._headers = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this._headers[sName] = sValue;
|
||||||
|
|
||||||
|
return this._object.setRequestHeader(sName, sValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
// EventTarget interface implementation
|
||||||
|
cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {
|
||||||
|
for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
|
||||||
|
if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add listener
|
||||||
|
this._listeners.push([sName, fHandler, bUseCapture]);
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
|
||||||
|
for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
|
||||||
|
if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove listener
|
||||||
|
if (oListener) {
|
||||||
|
this._listeners.splice(nIndex, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
|
||||||
|
var oEventPseudo = {
|
||||||
|
'type': oEvent.type,
|
||||||
|
'target': this,
|
||||||
|
'currentTarget': this,
|
||||||
|
'eventPhase': 2,
|
||||||
|
'bubbles': oEvent.bubbles,
|
||||||
|
'cancelable': oEvent.cancelable,
|
||||||
|
'timeStamp': oEvent.timeStamp,
|
||||||
|
'stopPropagation': function() {}, // There is no flow
|
||||||
|
'preventDefault': function() {}, // There is no default action
|
||||||
|
'initEvent': function() {} // Original event object should be initialized
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute onreadystatechange
|
||||||
|
if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) {
|
||||||
|
(this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Execute listeners
|
||||||
|
for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
|
||||||
|
if (oListener[0] == oEventPseudo.type && !oListener[2]) {
|
||||||
|
(oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
cXMLHttpRequest.prototype.toString = function() {
|
||||||
|
return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
|
||||||
|
};
|
||||||
|
|
||||||
|
cXMLHttpRequest.toString = function() {
|
||||||
|
return '[' + "XMLHttpRequest" + ']';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* // Queue manager
|
||||||
|
* var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
|
||||||
|
* aQueueRunning = [];
|
||||||
|
* function fQueue_add(oRequest) {
|
||||||
|
* oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
|
||||||
|
* //
|
||||||
|
* setTimeout(fQueue_process);
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* function fQueue_remove(oRequest) {
|
||||||
|
* for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
|
||||||
|
* if (bFound) {
|
||||||
|
* aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
|
||||||
|
* } else {
|
||||||
|
* if (aQueueRunning[nIndex] == oRequest) {
|
||||||
|
* bFound = true;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* if (bFound) {
|
||||||
|
* aQueueRunning.length--;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* //
|
||||||
|
* setTimeout(fQueue_process);
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* function fQueue_process() {
|
||||||
|
* if (aQueueRunning.length < 6) {
|
||||||
|
* for (var sPriority in oQueuePending) {
|
||||||
|
* if (oQueuePending[sPriority].length) {
|
||||||
|
* var oRequest = oQueuePending[sPriority][0];
|
||||||
|
* oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);
|
||||||
|
* //
|
||||||
|
* aQueueRunning.push(oRequest);
|
||||||
|
* // Send request
|
||||||
|
* fXMLHttpRequest_send(oRequest);
|
||||||
|
* break;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Helper function
|
||||||
|
function fXMLHttpRequest_send(oRequest) {
|
||||||
|
oRequest._object.send(oRequest._data);
|
||||||
|
|
||||||
|
// BUGFIX: Gecko - missing readystatechange calls in synchronous requests
|
||||||
|
if (bGecko && !oRequest._async) {
|
||||||
|
oRequest.readyState = cXMLHttpRequest.OPENED;
|
||||||
|
|
||||||
|
// Synchronize state
|
||||||
|
fSynchronizeValues(oRequest);
|
||||||
|
|
||||||
|
// Simulate missing states
|
||||||
|
while (oRequest.readyState < cXMLHttpRequest.DONE) {
|
||||||
|
oRequest.readyState++;
|
||||||
|
fReadyStateChange(oRequest);
|
||||||
|
// Check if we are aborted
|
||||||
|
if (oRequest._aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fReadyStateChange(oRequest) {
|
||||||
|
// Sniffing code
|
||||||
|
if (cXMLHttpRequest.onreadystatechange){
|
||||||
|
cXMLHttpRequest.onreadystatechange.apply(oRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fake event
|
||||||
|
oRequest.dispatchEvent({
|
||||||
|
'type': "readystatechange",
|
||||||
|
'bubbles': false,
|
||||||
|
'cancelable': false,
|
||||||
|
'timeStamp': new Date + 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fGetDocument(oRequest) {
|
||||||
|
var oDocument = oRequest.responseXML;
|
||||||
|
var sResponse = oRequest.responseText;
|
||||||
|
// Try parsing responseText
|
||||||
|
if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
|
||||||
|
oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
|
||||||
|
oDocument.async = false;
|
||||||
|
oDocument.validateOnParse = false;
|
||||||
|
oDocument.loadXML(sResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is no error in document
|
||||||
|
if (oDocument){
|
||||||
|
if ((bIE && oDocument.parseError !== 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fSynchronizeValues(oRequest) {
|
||||||
|
try { oRequest.responseText = oRequest._object.responseText; } catch (e) {}
|
||||||
|
try { oRequest.responseXML = fGetDocument(oRequest._object); } catch (e) {}
|
||||||
|
try { oRequest.status = oRequest._object.status; } catch (e) {}
|
||||||
|
try { oRequest.statusText = oRequest._object.statusText; } catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fCleanTransport(oRequest) {
|
||||||
|
// BUGFIX: IE - memory leak (on-page leak)
|
||||||
|
oRequest._object.onreadystatechange = new window.Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internet Explorer 5.0 (missing apply)
|
||||||
|
if (!window.Function.prototype.apply) {
|
||||||
|
window.Function.prototype.apply = function(oRequest, oArguments) {
|
||||||
|
if (!oArguments) {
|
||||||
|
oArguments = [];
|
||||||
|
}
|
||||||
|
oRequest.__func = this;
|
||||||
|
oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
|
||||||
|
delete oRequest.__func;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register new object with window
|
||||||
|
window.XMLHttpRequest = cXMLHttpRequest;
|
||||||
|
|
||||||
|
})();
|
2185
node_modules/esprima/test/3rdparty/ZeParser.js
generated
vendored
Normal file
2185
node_modules/esprima/test/3rdparty/ZeParser.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1158
node_modules/esprima/test/3rdparty/backbone-0.5.3.js
generated
vendored
Normal file
1158
node_modules/esprima/test/3rdparty/backbone-0.5.3.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3261
node_modules/esprima/test/3rdparty/benchmark.js
generated
vendored
Normal file
3261
node_modules/esprima/test/3rdparty/benchmark.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6579
node_modules/esprima/test/3rdparty/ext-core-3.0.0.js
generated
vendored
Normal file
6579
node_modules/esprima/test/3rdparty/ext-core-3.0.0.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10255
node_modules/esprima/test/3rdparty/ext-core-3.1.0.js
generated
vendored
Normal file
10255
node_modules/esprima/test/3rdparty/ext-core-3.1.0.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9046
node_modules/esprima/test/3rdparty/jquery-1.6.4.js
generated
vendored
Normal file
9046
node_modules/esprima/test/3rdparty/jquery-1.6.4.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9266
node_modules/esprima/test/3rdparty/jquery-1.7.1.js
generated
vendored
Normal file
9266
node_modules/esprima/test/3rdparty/jquery-1.7.1.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6951
node_modules/esprima/test/3rdparty/jquery.mobile-1.0.js
generated
vendored
Normal file
6951
node_modules/esprima/test/3rdparty/jquery.mobile-1.0.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
731
node_modules/esprima/test/3rdparty/jsdefs.js
generated
vendored
Normal file
731
node_modules/esprima/test/3rdparty/jsdefs.js
generated
vendored
Normal file
@ -0,0 +1,731 @@
|
|||||||
|
/* vim: set sw=4 ts=4 et tw=78: */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is the Narcissus JavaScript engine.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Brendan Eich <brendan@mozilla.org>.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Tom Austin <taustin@ucsc.edu>
|
||||||
|
* Brendan Eich <brendan@mozilla.org>
|
||||||
|
* Shu-Yu Guo <shu@rfrn.org>
|
||||||
|
* Dave Herman <dherman@mozilla.com>
|
||||||
|
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||||
|
* Patrick Walton <pcwalton@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Narcissus - JS implemented in JS.
|
||||||
|
*
|
||||||
|
* Well-known constants and lookup tables. Many consts are generated from the
|
||||||
|
* tokens table via eval to minimize redundancy, so consumers must be compiled
|
||||||
|
* separately to take advantage of the simple switch-case constant propagation
|
||||||
|
* done by SpiderMonkey.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var narcissus = {
|
||||||
|
options: {
|
||||||
|
version: 185,
|
||||||
|
// Global variables to hide from the interpreter
|
||||||
|
hiddenHostGlobals: { Narcissus: true },
|
||||||
|
// Desugar SpiderMonkey language extensions?
|
||||||
|
desugarExtensions: false,
|
||||||
|
// Allow HTML comments?
|
||||||
|
allowHTMLComments: false
|
||||||
|
},
|
||||||
|
hostSupportsEvalConst: (function() {
|
||||||
|
try {
|
||||||
|
return eval("(function(s) { eval(s); return x })('const x = true;')");
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
hostGlobal: this
|
||||||
|
};
|
||||||
|
Narcissus = narcissus;
|
||||||
|
})();
|
||||||
|
|
||||||
|
Narcissus.definitions = (function() {
|
||||||
|
|
||||||
|
var tokens = [
|
||||||
|
// End of source.
|
||||||
|
"END",
|
||||||
|
|
||||||
|
// Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
|
||||||
|
// and (UNARY_PLUS, UNARY_MINUS).
|
||||||
|
"\n", ";",
|
||||||
|
",",
|
||||||
|
"=",
|
||||||
|
"?", ":", "CONDITIONAL",
|
||||||
|
"||",
|
||||||
|
"&&",
|
||||||
|
"|",
|
||||||
|
"^",
|
||||||
|
"&",
|
||||||
|
"==", "!=", "===", "!==",
|
||||||
|
"<", "<=", ">=", ">",
|
||||||
|
"<<", ">>", ">>>",
|
||||||
|
"+", "-",
|
||||||
|
"*", "/", "%",
|
||||||
|
"!", "~", "UNARY_PLUS", "UNARY_MINUS",
|
||||||
|
"++", "--",
|
||||||
|
".",
|
||||||
|
"[", "]",
|
||||||
|
"{", "}",
|
||||||
|
"(", ")",
|
||||||
|
|
||||||
|
// Nonterminal tree node type codes.
|
||||||
|
"SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
|
||||||
|
"ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
|
||||||
|
"GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
|
||||||
|
|
||||||
|
// Terminals.
|
||||||
|
"IDENTIFIER", "NUMBER", "STRING", "REGEXP",
|
||||||
|
|
||||||
|
// Keywords.
|
||||||
|
"break",
|
||||||
|
"case", "catch", "const", "continue",
|
||||||
|
"debugger", "default", "delete", "do",
|
||||||
|
"else", "export",
|
||||||
|
"false", "finally", "for", "function",
|
||||||
|
"if", "import", "in", "instanceof",
|
||||||
|
"let", "module",
|
||||||
|
"new", "null",
|
||||||
|
"return",
|
||||||
|
"switch",
|
||||||
|
"this", "throw", "true", "try", "typeof",
|
||||||
|
"var", "void",
|
||||||
|
"yield",
|
||||||
|
"while", "with",
|
||||||
|
];
|
||||||
|
|
||||||
|
var statementStartTokens = [
|
||||||
|
"break",
|
||||||
|
"const", "continue",
|
||||||
|
"debugger", "do",
|
||||||
|
"for",
|
||||||
|
"if",
|
||||||
|
"return",
|
||||||
|
"switch",
|
||||||
|
"throw", "try",
|
||||||
|
"var",
|
||||||
|
"yield",
|
||||||
|
"while", "with",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Whitespace characters (see ECMA-262 7.2)
|
||||||
|
var whitespaceChars = [
|
||||||
|
// normal whitespace:
|
||||||
|
"\u0009", "\u000B", "\u000C", "\u0020", "\u00A0", "\uFEFF",
|
||||||
|
|
||||||
|
// high-Unicode whitespace:
|
||||||
|
"\u1680", "\u180E",
|
||||||
|
"\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006",
|
||||||
|
"\u2007", "\u2008", "\u2009", "\u200A",
|
||||||
|
"\u202F", "\u205F", "\u3000"
|
||||||
|
];
|
||||||
|
|
||||||
|
var whitespace = {};
|
||||||
|
for (var i = 0; i < whitespaceChars.length; i++) {
|
||||||
|
whitespace[whitespaceChars[i]] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operator and punctuator mapping from token to tree node type name.
|
||||||
|
// NB: because the lexer doesn't backtrack, all token prefixes must themselves
|
||||||
|
// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
|
||||||
|
// tokens != and !).
|
||||||
|
var opTypeNames = {
|
||||||
|
'\n': "NEWLINE",
|
||||||
|
';': "SEMICOLON",
|
||||||
|
',': "COMMA",
|
||||||
|
'?': "HOOK",
|
||||||
|
':': "COLON",
|
||||||
|
'||': "OR",
|
||||||
|
'&&': "AND",
|
||||||
|
'|': "BITWISE_OR",
|
||||||
|
'^': "BITWISE_XOR",
|
||||||
|
'&': "BITWISE_AND",
|
||||||
|
'===': "STRICT_EQ",
|
||||||
|
'==': "EQ",
|
||||||
|
'=': "ASSIGN",
|
||||||
|
'!==': "STRICT_NE",
|
||||||
|
'!=': "NE",
|
||||||
|
'<<': "LSH",
|
||||||
|
'<=': "LE",
|
||||||
|
'<': "LT",
|
||||||
|
'>>>': "URSH",
|
||||||
|
'>>': "RSH",
|
||||||
|
'>=': "GE",
|
||||||
|
'>': "GT",
|
||||||
|
'++': "INCREMENT",
|
||||||
|
'--': "DECREMENT",
|
||||||
|
'+': "PLUS",
|
||||||
|
'-': "MINUS",
|
||||||
|
'*': "MUL",
|
||||||
|
'/': "DIV",
|
||||||
|
'%': "MOD",
|
||||||
|
'!': "NOT",
|
||||||
|
'~': "BITWISE_NOT",
|
||||||
|
'.': "DOT",
|
||||||
|
'[': "LEFT_BRACKET",
|
||||||
|
']': "RIGHT_BRACKET",
|
||||||
|
'{': "LEFT_CURLY",
|
||||||
|
'}': "RIGHT_CURLY",
|
||||||
|
'(': "LEFT_PAREN",
|
||||||
|
')': "RIGHT_PAREN"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
|
||||||
|
// avoid toString, etc. namespace pollution.
|
||||||
|
var keywords = {__proto__: null};
|
||||||
|
|
||||||
|
// Define const END, etc., based on the token names. Also map name to index.
|
||||||
|
var tokenIds = {};
|
||||||
|
|
||||||
|
// Building up a string to be eval'd in different contexts.
|
||||||
|
var consts = Narcissus.hostSupportsEvalConst ? "const " : "var ";
|
||||||
|
for (var i = 0, j = tokens.length; i < j; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
consts += ", ";
|
||||||
|
var t = tokens[i];
|
||||||
|
var name;
|
||||||
|
if (/^[a-z]/.test(t)) {
|
||||||
|
name = t.toUpperCase();
|
||||||
|
keywords[t] = i;
|
||||||
|
} else {
|
||||||
|
name = (/^\W/.test(t) ? opTypeNames[t] : t);
|
||||||
|
}
|
||||||
|
consts += name + " = " + i;
|
||||||
|
tokenIds[name] = i;
|
||||||
|
tokens[t] = i;
|
||||||
|
}
|
||||||
|
consts += ";";
|
||||||
|
|
||||||
|
var isStatementStartCode = {__proto__: null};
|
||||||
|
for (i = 0, j = statementStartTokens.length; i < j; i++)
|
||||||
|
isStatementStartCode[keywords[statementStartTokens[i]]] = true;
|
||||||
|
|
||||||
|
// Map assignment operators to their indexes in the tokens array.
|
||||||
|
var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
|
||||||
|
|
||||||
|
for (i = 0, j = assignOps.length; i < j; i++) {
|
||||||
|
t = assignOps[i];
|
||||||
|
assignOps[t] = tokens[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||||
|
Object.defineProperty(obj, prop,
|
||||||
|
{ get: fn, configurable: !dontDelete, enumerable: !dontEnum });
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) {
|
||||||
|
Object.defineProperty(obj, prop, {
|
||||||
|
get: getter,
|
||||||
|
set: setter,
|
||||||
|
configurable: !dontDelete,
|
||||||
|
enumerable: !dontEnum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) {
|
||||||
|
Object.defineProperty(obj, prop, {
|
||||||
|
get: function() {
|
||||||
|
var val = fn();
|
||||||
|
defineProperty(obj, prop, val, dontDelete, true, dontEnum);
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
configurable: true,
|
||||||
|
enumerable: !dontEnum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
|
||||||
|
Object.defineProperty(obj, prop,
|
||||||
|
{ value: val, writable: !readOnly, configurable: !dontDelete,
|
||||||
|
enumerable: !dontEnum });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if fn is a native function. (Note: SpiderMonkey specific.)
|
||||||
|
function isNativeCode(fn) {
|
||||||
|
// Relies on the toString method to identify native code.
|
||||||
|
return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
|
||||||
|
}
|
||||||
|
|
||||||
|
var Fpapply = Function.prototype.apply;
|
||||||
|
|
||||||
|
function apply(f, o, a) {
|
||||||
|
return Fpapply.call(f, [o].concat(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
var applyNew;
|
||||||
|
|
||||||
|
// ES5's bind is a simpler way to implement applyNew
|
||||||
|
if (Function.prototype.bind) {
|
||||||
|
applyNew = function applyNew(f, a) {
|
||||||
|
return new (f.bind.apply(f, [,].concat(a)))();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
applyNew = function applyNew(f, a) {
|
||||||
|
switch (a.length) {
|
||||||
|
case 0:
|
||||||
|
return new f();
|
||||||
|
case 1:
|
||||||
|
return new f(a[0]);
|
||||||
|
case 2:
|
||||||
|
return new f(a[0], a[1]);
|
||||||
|
case 3:
|
||||||
|
return new f(a[0], a[1], a[2]);
|
||||||
|
default:
|
||||||
|
var argStr = "a[0]";
|
||||||
|
for (var i = 1, n = a.length; i < n; i++)
|
||||||
|
argStr += ",a[" + i + "]";
|
||||||
|
return eval("new f(" + argStr + ")");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPropertyDescriptor(obj, name) {
|
||||||
|
while (obj) {
|
||||||
|
if (({}).hasOwnProperty.call(obj, name))
|
||||||
|
return Object.getOwnPropertyDescriptor(obj, name);
|
||||||
|
obj = Object.getPrototypeOf(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPropertyNames(obj) {
|
||||||
|
var table = Object.create(null, {});
|
||||||
|
while (obj) {
|
||||||
|
var names = Object.getOwnPropertyNames(obj);
|
||||||
|
for (var i = 0, n = names.length; i < n; i++)
|
||||||
|
table[names[i]] = true;
|
||||||
|
obj = Object.getPrototypeOf(obj);
|
||||||
|
}
|
||||||
|
return Object.keys(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOwnProperties(obj) {
|
||||||
|
var map = {};
|
||||||
|
for (var name in Object.getOwnPropertyNames(obj))
|
||||||
|
map[name] = Object.getOwnPropertyDescriptor(obj, name);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
function blacklistHandler(target, blacklist) {
|
||||||
|
var mask = Object.create(null, {});
|
||||||
|
var redirect = StringMap.create(blacklist).mapObject(function(name) { return mask; });
|
||||||
|
return mixinHandler(redirect, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
function whitelistHandler(target, whitelist) {
|
||||||
|
var catchall = Object.create(null, {});
|
||||||
|
var redirect = StringMap.create(whitelist).mapObject(function(name) { return target; });
|
||||||
|
return mixinHandler(redirect, catchall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mirrorHandler(target, writable) {
|
||||||
|
var handler = makePassthruHandler(target);
|
||||||
|
|
||||||
|
var defineProperty = handler.defineProperty;
|
||||||
|
handler.defineProperty = function(name, desc) {
|
||||||
|
if (!desc.enumerable)
|
||||||
|
throw new Error("mirror property must be enumerable");
|
||||||
|
if (!desc.configurable)
|
||||||
|
throw new Error("mirror property must be configurable");
|
||||||
|
if (desc.writable !== writable)
|
||||||
|
throw new Error("mirror property must " + (writable ? "" : "not ") + "be writable");
|
||||||
|
defineProperty(name, desc);
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.fix = function() { };
|
||||||
|
handler.getOwnPropertyDescriptor = handler.getPropertyDescriptor;
|
||||||
|
handler.getOwnPropertyNames = getPropertyNames.bind(handler, target);
|
||||||
|
handler.keys = handler.enumerate;
|
||||||
|
handler["delete"] = function() { return false; };
|
||||||
|
handler.hasOwn = handler.has;
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mixin proxies break the single-inheritance model of prototypes, so
|
||||||
|
* the handler treats all properties as own-properties:
|
||||||
|
*
|
||||||
|
* X
|
||||||
|
* |
|
||||||
|
* +------------+------------+
|
||||||
|
* | O |
|
||||||
|
* | | |
|
||||||
|
* | O O O |
|
||||||
|
* | | | | |
|
||||||
|
* | O O O O |
|
||||||
|
* | | | | | |
|
||||||
|
* | O O O O O |
|
||||||
|
* | | | | | | |
|
||||||
|
* +-(*)--(w)--(x)--(y)--(z)-+
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mixinHandler(redirect, catchall) {
|
||||||
|
function targetFor(name) {
|
||||||
|
return hasOwn(redirect, name) ? redirect[name] : catchall;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMuxPropertyDescriptor(name) {
|
||||||
|
var desc = getPropertyDescriptor(targetFor(name), name);
|
||||||
|
if (desc)
|
||||||
|
desc.configurable = true;
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMuxPropertyNames() {
|
||||||
|
var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) {
|
||||||
|
return name in redirect[name];
|
||||||
|
});
|
||||||
|
var names2 = getPropertyNames(catchall).filter(function(name) {
|
||||||
|
return !hasOwn(redirect, name);
|
||||||
|
});
|
||||||
|
return names1.concat(names2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enumerateMux() {
|
||||||
|
var result = Object.getOwnPropertyNames(redirect).filter(function(name) {
|
||||||
|
return name in redirect[name];
|
||||||
|
});
|
||||||
|
for (name in catchall) {
|
||||||
|
if (!hasOwn(redirect, name))
|
||||||
|
result.push(name);
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasMux(name) {
|
||||||
|
return name in targetFor(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getOwnPropertyDescriptor: getMuxPropertyDescriptor,
|
||||||
|
getPropertyDescriptor: getMuxPropertyDescriptor,
|
||||||
|
getOwnPropertyNames: getMuxPropertyNames,
|
||||||
|
defineProperty: function(name, desc) {
|
||||||
|
Object.defineProperty(targetFor(name), name, desc);
|
||||||
|
},
|
||||||
|
"delete": function(name) {
|
||||||
|
var target = targetFor(name);
|
||||||
|
return delete target[name];
|
||||||
|
},
|
||||||
|
// FIXME: ha ha ha
|
||||||
|
fix: function() { },
|
||||||
|
has: hasMux,
|
||||||
|
hasOwn: hasMux,
|
||||||
|
get: function(receiver, name) {
|
||||||
|
var target = targetFor(name);
|
||||||
|
return target[name];
|
||||||
|
},
|
||||||
|
set: function(receiver, name, val) {
|
||||||
|
var target = targetFor(name);
|
||||||
|
target[name] = val;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
enumerate: enumerateMux,
|
||||||
|
keys: enumerateMux
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePassthruHandler(obj) {
|
||||||
|
// Handler copied from
|
||||||
|
// http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
|
||||||
|
return {
|
||||||
|
getOwnPropertyDescriptor: function(name) {
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||||
|
|
||||||
|
// a trapping proxy's properties must always be configurable
|
||||||
|
desc.configurable = true;
|
||||||
|
return desc;
|
||||||
|
},
|
||||||
|
getPropertyDescriptor: function(name) {
|
||||||
|
var desc = getPropertyDescriptor(obj, name);
|
||||||
|
|
||||||
|
// a trapping proxy's properties must always be configurable
|
||||||
|
desc.configurable = true;
|
||||||
|
return desc;
|
||||||
|
},
|
||||||
|
getOwnPropertyNames: function() {
|
||||||
|
return Object.getOwnPropertyNames(obj);
|
||||||
|
},
|
||||||
|
defineProperty: function(name, desc) {
|
||||||
|
Object.defineProperty(obj, name, desc);
|
||||||
|
},
|
||||||
|
"delete": function(name) { return delete obj[name]; },
|
||||||
|
fix: function() {
|
||||||
|
if (Object.isFrozen(obj)) {
|
||||||
|
return getOwnProperties(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// As long as obj is not frozen, the proxy won't allow itself to be fixed.
|
||||||
|
return undefined; // will cause a TypeError to be thrown
|
||||||
|
},
|
||||||
|
|
||||||
|
has: function(name) { return name in obj; },
|
||||||
|
hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
||||||
|
get: function(receiver, name) { return obj[name]; },
|
||||||
|
|
||||||
|
// bad behavior when set fails in non-strict mode
|
||||||
|
set: function(receiver, name, val) { obj[name] = val; return true; },
|
||||||
|
enumerate: function() {
|
||||||
|
var result = [];
|
||||||
|
for (name in obj) { result.push(name); };
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
keys: function() { return Object.keys(obj); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasOwnProperty = ({}).hasOwnProperty;
|
||||||
|
|
||||||
|
function hasOwn(obj, name) {
|
||||||
|
return hasOwnProperty.call(obj, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function StringMap(table, size) {
|
||||||
|
this.table = table || Object.create(null, {});
|
||||||
|
this.size = size || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringMap.create = function(table) {
|
||||||
|
var init = Object.create(null, {});
|
||||||
|
var size = 0;
|
||||||
|
var names = Object.getOwnPropertyNames(table);
|
||||||
|
for (var i = 0, n = names.length; i < n; i++) {
|
||||||
|
var name = names[i];
|
||||||
|
init[name] = table[name];
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
return new StringMap(init, size);
|
||||||
|
};
|
||||||
|
|
||||||
|
StringMap.prototype = {
|
||||||
|
has: function(x) { return hasOwnProperty.call(this.table, x); },
|
||||||
|
set: function(x, v) {
|
||||||
|
if (!hasOwnProperty.call(this.table, x))
|
||||||
|
this.size++;
|
||||||
|
this.table[x] = v;
|
||||||
|
},
|
||||||
|
get: function(x) { return this.table[x]; },
|
||||||
|
getDef: function(x, thunk) {
|
||||||
|
if (!hasOwnProperty.call(this.table, x)) {
|
||||||
|
this.size++;
|
||||||
|
this.table[x] = thunk();
|
||||||
|
}
|
||||||
|
return this.table[x];
|
||||||
|
},
|
||||||
|
forEach: function(f) {
|
||||||
|
var table = this.table;
|
||||||
|
for (var key in table)
|
||||||
|
f.call(this, key, table[key]);
|
||||||
|
},
|
||||||
|
map: function(f) {
|
||||||
|
var table1 = this.table;
|
||||||
|
var table2 = Object.create(null, {});
|
||||||
|
this.forEach(function(key, val) {
|
||||||
|
table2[key] = f.call(this, val, key);
|
||||||
|
});
|
||||||
|
return new StringMap(table2, this.size);
|
||||||
|
},
|
||||||
|
mapObject: function(f) {
|
||||||
|
var table1 = this.table;
|
||||||
|
var table2 = Object.create(null, {});
|
||||||
|
this.forEach(function(key, val) {
|
||||||
|
table2[key] = f.call(this, val, key);
|
||||||
|
});
|
||||||
|
return table2;
|
||||||
|
},
|
||||||
|
toObject: function() {
|
||||||
|
return this.mapObject(function(val) { return val; });
|
||||||
|
},
|
||||||
|
choose: function() {
|
||||||
|
return Object.getOwnPropertyNames(this.table)[0];
|
||||||
|
},
|
||||||
|
remove: function(x) {
|
||||||
|
if (hasOwnProperty.call(this.table, x)) {
|
||||||
|
this.size--;
|
||||||
|
delete this.table[x];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
copy: function() {
|
||||||
|
var table = Object.create(null, {});
|
||||||
|
for (var key in this.table)
|
||||||
|
table[key] = this.table[key];
|
||||||
|
return new StringMap(table, this.size);
|
||||||
|
},
|
||||||
|
keys: function() {
|
||||||
|
return Object.keys(this.table);
|
||||||
|
},
|
||||||
|
toString: function() { return "[object StringMap]" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// an object-key table with poor asymptotics (replace with WeakMap when possible)
|
||||||
|
function ObjectMap(array) {
|
||||||
|
this.array = array || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchMap(map, key, found, notFound) {
|
||||||
|
var a = map.array;
|
||||||
|
for (var i = 0, n = a.length; i < n; i++) {
|
||||||
|
var pair = a[i];
|
||||||
|
if (pair.key === key)
|
||||||
|
return found(pair, i);
|
||||||
|
}
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectMap.prototype = {
|
||||||
|
has: function(x) {
|
||||||
|
return searchMap(this, x, function() { return true }, function() { return false });
|
||||||
|
},
|
||||||
|
set: function(x, v) {
|
||||||
|
var a = this.array;
|
||||||
|
searchMap(this, x,
|
||||||
|
function(pair) { pair.value = v },
|
||||||
|
function() { a.push({ key: x, value: v }) });
|
||||||
|
},
|
||||||
|
get: function(x) {
|
||||||
|
return searchMap(this, x,
|
||||||
|
function(pair) { return pair.value },
|
||||||
|
function() { return null });
|
||||||
|
},
|
||||||
|
getDef: function(x, thunk) {
|
||||||
|
var a = this.array;
|
||||||
|
return searchMap(this, x,
|
||||||
|
function(pair) { return pair.value },
|
||||||
|
function() {
|
||||||
|
var v = thunk();
|
||||||
|
a.push({ key: x, value: v });
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
forEach: function(f) {
|
||||||
|
var a = this.array;
|
||||||
|
for (var i = 0, n = a.length; i < n; i++) {
|
||||||
|
var pair = a[i];
|
||||||
|
f.call(this, pair.key, pair.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
choose: function() {
|
||||||
|
return this.array[0].key;
|
||||||
|
},
|
||||||
|
get size() {
|
||||||
|
return this.array.length;
|
||||||
|
},
|
||||||
|
remove: function(x) {
|
||||||
|
var a = this.array;
|
||||||
|
searchMap(this, x,
|
||||||
|
function(pair, i) { a.splice(i, 1) },
|
||||||
|
function() { });
|
||||||
|
},
|
||||||
|
copy: function() {
|
||||||
|
return new ObjectMap(this.array.map(function(pair) {
|
||||||
|
return { key: pair.key, value: pair.value }
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
clear: function() {
|
||||||
|
this.array = [];
|
||||||
|
},
|
||||||
|
toString: function() { return "[object ObjectMap]" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// non-destructive stack
|
||||||
|
function Stack(elts) {
|
||||||
|
this.elts = elts || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack.prototype = {
|
||||||
|
push: function(x) {
|
||||||
|
return new Stack({ top: x, rest: this.elts });
|
||||||
|
},
|
||||||
|
top: function() {
|
||||||
|
if (!this.elts)
|
||||||
|
throw new Error("empty stack");
|
||||||
|
return this.elts.top;
|
||||||
|
},
|
||||||
|
isEmpty: function() {
|
||||||
|
return this.top === null;
|
||||||
|
},
|
||||||
|
find: function(test) {
|
||||||
|
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||||
|
if (test(elts.top))
|
||||||
|
return elts.top;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
has: function(x) {
|
||||||
|
return Boolean(this.find(function(elt) { return elt === x }));
|
||||||
|
},
|
||||||
|
forEach: function(f) {
|
||||||
|
for (var elts = this.elts; elts; elts = elts.rest) {
|
||||||
|
f(elts.top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!Array.prototype.copy) {
|
||||||
|
Array.prototype.copy = function() {
|
||||||
|
var result = [];
|
||||||
|
for (var i = 0, n = this.length; i < n; i++)
|
||||||
|
result[i] = this[i];
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tokens: tokens,
|
||||||
|
whitespace: whitespace,
|
||||||
|
opTypeNames: opTypeNames,
|
||||||
|
keywords: keywords,
|
||||||
|
isStatementStartCode: isStatementStartCode,
|
||||||
|
tokenIds: tokenIds,
|
||||||
|
consts: consts,
|
||||||
|
assignOps: assignOps,
|
||||||
|
defineGetter: defineGetter,
|
||||||
|
defineGetterSetter: defineGetterSetter,
|
||||||
|
defineMemoGetter: defineMemoGetter,
|
||||||
|
defineProperty: defineProperty,
|
||||||
|
isNativeCode: isNativeCode,
|
||||||
|
apply: apply,
|
||||||
|
applyNew: applyNew,
|
||||||
|
mirrorHandler: mirrorHandler,
|
||||||
|
mixinHandler: mixinHandler,
|
||||||
|
whitelistHandler: whitelistHandler,
|
||||||
|
blacklistHandler: blacklistHandler,
|
||||||
|
makePassthruHandler: makePassthruHandler,
|
||||||
|
StringMap: StringMap,
|
||||||
|
ObjectMap: ObjectMap,
|
||||||
|
Stack: Stack
|
||||||
|
};
|
||||||
|
}());
|
588
node_modules/esprima/test/3rdparty/jslex.js
generated
vendored
Normal file
588
node_modules/esprima/test/3rdparty/jslex.js
generated
vendored
Normal file
@ -0,0 +1,588 @@
|
|||||||
|
/* vim: set sw=4 ts=4 et tw=78: */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is the Narcissus JavaScript engine.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Brendan Eich <brendan@mozilla.org>.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Tom Austin <taustin@ucsc.edu>
|
||||||
|
* Brendan Eich <brendan@mozilla.org>
|
||||||
|
* Shu-Yu Guo <shu@rfrn.org>
|
||||||
|
* Stephan Herhut <stephan.a.herhut@intel.com>
|
||||||
|
* Dave Herman <dherman@mozilla.com>
|
||||||
|
* Dimitris Vardoulakis <dimvar@ccs.neu.edu>
|
||||||
|
* Patrick Walton <pcwalton@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Narcissus - JS implemented in JS.
|
||||||
|
*
|
||||||
|
* Lexical scanner.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Narcissus.lexer = (function() {
|
||||||
|
|
||||||
|
var definitions = Narcissus.definitions;
|
||||||
|
|
||||||
|
// Set constants in the local scope.
|
||||||
|
eval(definitions.consts);
|
||||||
|
|
||||||
|
// Banned keywords by language version
|
||||||
|
const blackLists = { 160: {}, 185: {}, harmony: {} };
|
||||||
|
blackLists[160][LET] = true;
|
||||||
|
blackLists[160][MODULE] = true;
|
||||||
|
blackLists[160][YIELD] = true;
|
||||||
|
blackLists[185][MODULE] = true;
|
||||||
|
|
||||||
|
// Build up a trie of operator tokens.
|
||||||
|
var opTokens = {};
|
||||||
|
for (var op in definitions.opTypeNames) {
|
||||||
|
if (op === '\n' || op === '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var node = opTokens;
|
||||||
|
for (var i = 0; i < op.length; i++) {
|
||||||
|
var ch = op[i];
|
||||||
|
if (!(ch in node))
|
||||||
|
node[ch] = {};
|
||||||
|
node = node[ch];
|
||||||
|
node.op = op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since JavaScript provides no convenient way to determine if a
|
||||||
|
* character is in a particular Unicode category, we use
|
||||||
|
* metacircularity to accomplish this (oh yeaaaah!)
|
||||||
|
*/
|
||||||
|
function isValidIdentifierChar(ch, first) {
|
||||||
|
// check directly for ASCII
|
||||||
|
if (ch <= "\u007F") {
|
||||||
|
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||
|
||||||
|
(!first && (ch >= '0' && ch <= '9'))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an object to test this in
|
||||||
|
var x = {};
|
||||||
|
x["x"+ch] = true;
|
||||||
|
x[ch] = true;
|
||||||
|
|
||||||
|
// then use eval to determine if it's a valid character
|
||||||
|
var valid = false;
|
||||||
|
try {
|
||||||
|
valid = (Function("x", "return (x." + (first?"":"x") + ch + ");")(x) === true);
|
||||||
|
} catch (ex) {}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIdentifier(str) {
|
||||||
|
if (typeof str !== "string")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (str.length === 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isValidIdentifierChar(str[0], true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var i = 1; i < str.length; i++) {
|
||||||
|
if (!isValidIdentifierChar(str[i], false))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tokenizer :: (source, filename, line number) -> Tokenizer
|
||||||
|
*/
|
||||||
|
function Tokenizer(s, f, l) {
|
||||||
|
this.cursor = 0;
|
||||||
|
this.source = String(s);
|
||||||
|
this.tokens = [];
|
||||||
|
this.tokenIndex = 0;
|
||||||
|
this.lookahead = 0;
|
||||||
|
this.scanNewlines = false;
|
||||||
|
this.unexpectedEOF = false;
|
||||||
|
this.filename = f || "";
|
||||||
|
this.lineno = l || 1;
|
||||||
|
this.blackList = blackLists[Narcissus.options.version];
|
||||||
|
this.blockComments = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokenizer.prototype = {
|
||||||
|
get done() {
|
||||||
|
// We need to set scanOperand to true here because the first thing
|
||||||
|
// might be a regexp.
|
||||||
|
return this.peek(true) === END;
|
||||||
|
},
|
||||||
|
|
||||||
|
get token() {
|
||||||
|
return this.tokens[this.tokenIndex];
|
||||||
|
},
|
||||||
|
|
||||||
|
match: function (tt, scanOperand, keywordIsName) {
|
||||||
|
return this.get(scanOperand, keywordIsName) === tt || this.unget();
|
||||||
|
},
|
||||||
|
|
||||||
|
mustMatch: function (tt, keywordIsName) {
|
||||||
|
if (!this.match(tt, false, keywordIsName)) {
|
||||||
|
throw this.newSyntaxError("Missing " +
|
||||||
|
definitions.tokens[tt].toLowerCase());
|
||||||
|
}
|
||||||
|
return this.token;
|
||||||
|
},
|
||||||
|
|
||||||
|
peek: function (scanOperand) {
|
||||||
|
var tt, next;
|
||||||
|
if (this.lookahead) {
|
||||||
|
next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
|
||||||
|
tt = (this.scanNewlines && next.lineno !== this.lineno)
|
||||||
|
? NEWLINE
|
||||||
|
: next.type;
|
||||||
|
} else {
|
||||||
|
tt = this.get(scanOperand);
|
||||||
|
this.unget();
|
||||||
|
}
|
||||||
|
return tt;
|
||||||
|
},
|
||||||
|
|
||||||
|
peekOnSameLine: function (scanOperand) {
|
||||||
|
this.scanNewlines = true;
|
||||||
|
var tt = this.peek(scanOperand);
|
||||||
|
this.scanNewlines = false;
|
||||||
|
return tt;
|
||||||
|
},
|
||||||
|
|
||||||
|
lastBlockComment: function() {
|
||||||
|
var length = this.blockComments.length;
|
||||||
|
return length ? this.blockComments[length - 1] : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Eat comments and whitespace.
|
||||||
|
skip: function () {
|
||||||
|
var input = this.source;
|
||||||
|
this.blockComments = [];
|
||||||
|
for (;;) {
|
||||||
|
var ch = input[this.cursor++];
|
||||||
|
var next = input[this.cursor];
|
||||||
|
// handle \r, \r\n and (always preferable) \n
|
||||||
|
if (ch === '\r') {
|
||||||
|
// if the next character is \n, we don't care about this at all
|
||||||
|
if (next === '\n') continue;
|
||||||
|
|
||||||
|
// otherwise, we want to consider this as a newline
|
||||||
|
ch = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '\n' && !this.scanNewlines) {
|
||||||
|
this.lineno++;
|
||||||
|
} else if (ch === '/' && next === '*') {
|
||||||
|
var commentStart = ++this.cursor;
|
||||||
|
for (;;) {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
if (ch === undefined)
|
||||||
|
throw this.newSyntaxError("Unterminated comment");
|
||||||
|
|
||||||
|
if (ch === '*') {
|
||||||
|
next = input[this.cursor];
|
||||||
|
if (next === '/') {
|
||||||
|
var commentEnd = this.cursor - 1;
|
||||||
|
this.cursor++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (ch === '\n') {
|
||||||
|
this.lineno++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.blockComments.push(input.substring(commentStart, commentEnd));
|
||||||
|
} else if ((ch === '/' && next === '/') ||
|
||||||
|
(Narcissus.options.allowHTMLComments && ch === '<' && next === '!' &&
|
||||||
|
input[this.cursor + 1] === '-' && input[this.cursor + 2] === '-' &&
|
||||||
|
(this.cursor += 2))) {
|
||||||
|
this.cursor++;
|
||||||
|
for (;;) {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
next = input[this.cursor];
|
||||||
|
if (ch === undefined)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ch === '\r') {
|
||||||
|
// check for \r\n
|
||||||
|
if (next !== '\n') ch = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '\n') {
|
||||||
|
if (this.scanNewlines) {
|
||||||
|
this.cursor--;
|
||||||
|
} else {
|
||||||
|
this.lineno++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!(ch in definitions.whitespace)) {
|
||||||
|
this.cursor--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Lex the exponential part of a number, if present. Return true iff an
|
||||||
|
// exponential part was found.
|
||||||
|
lexExponent: function() {
|
||||||
|
var input = this.source;
|
||||||
|
var next = input[this.cursor];
|
||||||
|
if (next === 'e' || next === 'E') {
|
||||||
|
this.cursor++;
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
if (ch === '+' || ch === '-')
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
|
||||||
|
if (ch < '0' || ch > '9')
|
||||||
|
throw this.newSyntaxError("Missing exponent");
|
||||||
|
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch >= '0' && ch <= '9');
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
lexZeroNumber: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
token.type = NUMBER;
|
||||||
|
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
if (ch === '.') {
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch >= '0' && ch <= '9');
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
this.lexExponent();
|
||||||
|
token.value = parseFloat(
|
||||||
|
input.substring(token.start, this.cursor));
|
||||||
|
} else if (ch === 'x' || ch === 'X') {
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
|
||||||
|
(ch >= 'A' && ch <= 'F'));
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||||
|
} else if (ch >= '0' && ch <= '7') {
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch >= '0' && ch <= '7');
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
token.value = parseInt(input.substring(token.start, this.cursor));
|
||||||
|
} else {
|
||||||
|
this.cursor--;
|
||||||
|
this.lexExponent(); // 0E1, &c.
|
||||||
|
token.value = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
lexNumber: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
token.type = NUMBER;
|
||||||
|
|
||||||
|
var floating = false;
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
if (ch === '.' && !floating) {
|
||||||
|
floating = true;
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
}
|
||||||
|
} while (ch >= '0' && ch <= '9');
|
||||||
|
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
var exponent = this.lexExponent();
|
||||||
|
floating = floating || exponent;
|
||||||
|
|
||||||
|
var str = input.substring(token.start, this.cursor);
|
||||||
|
token.value = floating ? parseFloat(str) : parseInt(str);
|
||||||
|
},
|
||||||
|
|
||||||
|
lexDot: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
var next = input[this.cursor];
|
||||||
|
if (next >= '0' && next <= '9') {
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch >= '0' && ch <= '9');
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
this.lexExponent();
|
||||||
|
|
||||||
|
token.type = NUMBER;
|
||||||
|
token.value = parseFloat(
|
||||||
|
input.substring(token.start, this.cursor));
|
||||||
|
} else {
|
||||||
|
token.type = DOT;
|
||||||
|
token.assignOp = null;
|
||||||
|
token.value = '.';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
lexString: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
token.type = STRING;
|
||||||
|
|
||||||
|
var hasEscapes = false;
|
||||||
|
var delim = ch;
|
||||||
|
if (input.length <= this.cursor)
|
||||||
|
throw this.newSyntaxError("Unterminated string literal");
|
||||||
|
while ((ch = input[this.cursor++]) !== delim) {
|
||||||
|
if (this.cursor == input.length)
|
||||||
|
throw this.newSyntaxError("Unterminated string literal");
|
||||||
|
if (ch === '\\') {
|
||||||
|
hasEscapes = true;
|
||||||
|
if (++this.cursor == input.length)
|
||||||
|
throw this.newSyntaxError("Unterminated string literal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
token.value = hasEscapes
|
||||||
|
? eval(input.substring(token.start, this.cursor))
|
||||||
|
: input.substring(token.start + 1, this.cursor - 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
lexRegExp: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
token.type = REGEXP;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
if (ch === '\\') {
|
||||||
|
this.cursor++;
|
||||||
|
} else if (ch === '[') {
|
||||||
|
do {
|
||||||
|
if (ch === undefined)
|
||||||
|
throw this.newSyntaxError("Unterminated character class");
|
||||||
|
|
||||||
|
if (ch === '\\')
|
||||||
|
this.cursor++;
|
||||||
|
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch !== ']');
|
||||||
|
} else if (ch === undefined) {
|
||||||
|
throw this.newSyntaxError("Unterminated regex");
|
||||||
|
}
|
||||||
|
} while (ch !== '/');
|
||||||
|
|
||||||
|
do {
|
||||||
|
ch = input[this.cursor++];
|
||||||
|
} while (ch >= 'a' && ch <= 'z');
|
||||||
|
|
||||||
|
this.cursor--;
|
||||||
|
|
||||||
|
token.value = eval(input.substring(token.start, this.cursor));
|
||||||
|
},
|
||||||
|
|
||||||
|
lexOp: function (ch) {
|
||||||
|
var token = this.token, input = this.source;
|
||||||
|
|
||||||
|
// A bit ugly, but it seems wasteful to write a trie lookup routine
|
||||||
|
// for only 3 characters...
|
||||||
|
var node = opTokens[ch];
|
||||||
|
var next = input[this.cursor];
|
||||||
|
if (next in node) {
|
||||||
|
node = node[next];
|
||||||
|
this.cursor++;
|
||||||
|
next = input[this.cursor];
|
||||||
|
if (next in node) {
|
||||||
|
node = node[next];
|
||||||
|
this.cursor++;
|
||||||
|
next = input[this.cursor];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var op = node.op;
|
||||||
|
if (definitions.assignOps[op] && input[this.cursor] === '=') {
|
||||||
|
this.cursor++;
|
||||||
|
token.type = ASSIGN;
|
||||||
|
token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||||
|
op += '=';
|
||||||
|
} else {
|
||||||
|
token.type = definitions.tokenIds[definitions.opTypeNames[op]];
|
||||||
|
token.assignOp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
token.value = op;
|
||||||
|
},
|
||||||
|
|
||||||
|
// FIXME: Unicode escape sequences
|
||||||
|
lexIdent: function (ch, keywordIsName) {
|
||||||
|
var token = this.token;
|
||||||
|
var id = ch;
|
||||||
|
|
||||||
|
while ((ch = this.getValidIdentifierChar(false)) !== null) {
|
||||||
|
id += ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
token.type = IDENTIFIER;
|
||||||
|
token.value = id;
|
||||||
|
|
||||||
|
if (keywordIsName)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var kw = definitions.keywords[id];
|
||||||
|
if (kw && !(kw in this.blackList))
|
||||||
|
token.type = kw;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tokenizer.get :: [boolean[, boolean]] -> token type
|
||||||
|
*
|
||||||
|
* Consume input *only* if there is no lookahead.
|
||||||
|
* Dispatch to the appropriate lexing function depending on the input.
|
||||||
|
*/
|
||||||
|
get: function (scanOperand, keywordIsName) {
|
||||||
|
var token;
|
||||||
|
while (this.lookahead) {
|
||||||
|
--this.lookahead;
|
||||||
|
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||||
|
token = this.tokens[this.tokenIndex];
|
||||||
|
if (token.type !== NEWLINE || this.scanNewlines)
|
||||||
|
return token.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skip();
|
||||||
|
|
||||||
|
this.tokenIndex = (this.tokenIndex + 1) & 3;
|
||||||
|
token = this.tokens[this.tokenIndex];
|
||||||
|
if (!token)
|
||||||
|
this.tokens[this.tokenIndex] = token = {};
|
||||||
|
|
||||||
|
var input = this.source;
|
||||||
|
if (this.cursor >= input.length)
|
||||||
|
return token.type = END;
|
||||||
|
|
||||||
|
token.start = this.cursor;
|
||||||
|
token.lineno = this.lineno;
|
||||||
|
|
||||||
|
var ich = this.getValidIdentifierChar(true);
|
||||||
|
var ch = (ich === null) ? input[this.cursor++] : null;
|
||||||
|
if (ich !== null) {
|
||||||
|
this.lexIdent(ich, keywordIsName);
|
||||||
|
} else if (scanOperand && ch === '/') {
|
||||||
|
this.lexRegExp(ch);
|
||||||
|
} else if (ch in opTokens) {
|
||||||
|
this.lexOp(ch);
|
||||||
|
} else if (ch === '.') {
|
||||||
|
this.lexDot(ch);
|
||||||
|
} else if (ch >= '1' && ch <= '9') {
|
||||||
|
this.lexNumber(ch);
|
||||||
|
} else if (ch === '0') {
|
||||||
|
this.lexZeroNumber(ch);
|
||||||
|
} else if (ch === '"' || ch === "'") {
|
||||||
|
this.lexString(ch);
|
||||||
|
} else if (this.scanNewlines && (ch === '\n' || ch === '\r')) {
|
||||||
|
// if this was a \r, look for \r\n
|
||||||
|
if (ch === '\r' && input[this.cursor] === '\n') this.cursor++;
|
||||||
|
token.type = NEWLINE;
|
||||||
|
token.value = '\n';
|
||||||
|
this.lineno++;
|
||||||
|
} else {
|
||||||
|
throw this.newSyntaxError("Illegal token");
|
||||||
|
}
|
||||||
|
|
||||||
|
token.end = this.cursor;
|
||||||
|
return token.type;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tokenizer.unget :: void -> undefined
|
||||||
|
*
|
||||||
|
* Match depends on unget returning undefined.
|
||||||
|
*/
|
||||||
|
unget: function () {
|
||||||
|
if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
|
||||||
|
this.tokenIndex = (this.tokenIndex - 1) & 3;
|
||||||
|
},
|
||||||
|
|
||||||
|
newSyntaxError: function (m) {
|
||||||
|
m = (this.filename ? this.filename + ":" : "") + this.lineno + ": " + m;
|
||||||
|
var e = new SyntaxError(m, this.filename, this.lineno);
|
||||||
|
e.source = this.source;
|
||||||
|
e.cursor = this.lookahead
|
||||||
|
? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
|
||||||
|
: this.cursor;
|
||||||
|
return e;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/* Gets a single valid identifier char from the input stream, or null
|
||||||
|
* if there is none.
|
||||||
|
*/
|
||||||
|
getValidIdentifierChar: function(first) {
|
||||||
|
var input = this.source;
|
||||||
|
if (this.cursor >= input.length) return null;
|
||||||
|
var ch = input[this.cursor];
|
||||||
|
|
||||||
|
// first check for \u escapes
|
||||||
|
if (ch === '\\' && input[this.cursor+1] === 'u') {
|
||||||
|
// get the character value
|
||||||
|
try {
|
||||||
|
ch = String.fromCharCode(parseInt(
|
||||||
|
input.substring(this.cursor + 2, this.cursor + 6),
|
||||||
|
16));
|
||||||
|
} catch (ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.cursor += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
var valid = isValidIdentifierChar(ch, first);
|
||||||
|
if (valid) this.cursor++;
|
||||||
|
return (valid ? ch : null);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
isIdentifier: isIdentifier,
|
||||||
|
Tokenizer: Tokenizer
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
1921
node_modules/esprima/test/3rdparty/jsparse.js
generated
vendored
Normal file
1921
node_modules/esprima/test/3rdparty/jsparse.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5952
node_modules/esprima/test/3rdparty/mootools-1.3.2.js
generated
vendored
Normal file
5952
node_modules/esprima/test/3rdparty/mootools-1.3.2.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6297
node_modules/esprima/test/3rdparty/mootools-1.4.1.js
generated
vendored
Normal file
6297
node_modules/esprima/test/3rdparty/mootools-1.4.1.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1342
node_modules/esprima/test/3rdparty/parse-js.js
generated
vendored
Normal file
1342
node_modules/esprima/test/3rdparty/parse-js.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
891
node_modules/esprima/test/3rdparty/platform.js
generated
vendored
Normal file
891
node_modules/esprima/test/3rdparty/platform.js
generated
vendored
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
/*!
|
||||||
|
* Platform.js <http://mths.be/platform>
|
||||||
|
* Copyright 2010-2011 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
* Available under MIT license <http://mths.be/mit>
|
||||||
|
*/
|
||||||
|
;(function(window) {
|
||||||
|
|
||||||
|
/** Backup possible window/global object */
|
||||||
|
var oldWin = window,
|
||||||
|
|
||||||
|
/** Possible global object */
|
||||||
|
thisBinding = this,
|
||||||
|
|
||||||
|
/** Detect free variable `exports` */
|
||||||
|
freeExports = typeof exports == 'object' && exports,
|
||||||
|
|
||||||
|
/** Detect free variable `global` */
|
||||||
|
freeGlobal = typeof global == 'object' && global && (global == global.global ? (window = global) : global),
|
||||||
|
|
||||||
|
/** Used to check for own properties of an object */
|
||||||
|
hasOwnProperty = {}.hasOwnProperty,
|
||||||
|
|
||||||
|
/** Used to resolve a value's internal [[Class]] */
|
||||||
|
toString = {}.toString,
|
||||||
|
|
||||||
|
/** Detect Java environment */
|
||||||
|
java = /Java/.test(getClassOf(window.java)) && window.java,
|
||||||
|
|
||||||
|
/** A character to represent alpha */
|
||||||
|
alpha = java ? 'a' : '\u03b1',
|
||||||
|
|
||||||
|
/** A character to represent beta */
|
||||||
|
beta = java ? 'b' : '\u03b2',
|
||||||
|
|
||||||
|
/** Browser document object */
|
||||||
|
doc = window.document || {},
|
||||||
|
|
||||||
|
/** Browser navigator object */
|
||||||
|
nav = window.navigator || {},
|
||||||
|
|
||||||
|
/** Previous platform object */
|
||||||
|
old = window.platform,
|
||||||
|
|
||||||
|
/** Browser user agent string */
|
||||||
|
userAgent = nav.userAgent || '',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect Opera browser
|
||||||
|
* http://www.howtocreate.co.uk/operaStuff/operaObject.html
|
||||||
|
* http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
|
||||||
|
*/
|
||||||
|
opera = window.operamini || window.opera,
|
||||||
|
|
||||||
|
/** Opera regexp */
|
||||||
|
reOpera = /Opera/,
|
||||||
|
|
||||||
|
/** Opera [[Class]] */
|
||||||
|
operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capitalizes a string value.
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to capitalize.
|
||||||
|
* @returns {String} The capitalized string.
|
||||||
|
*/
|
||||||
|
function capitalize(string) {
|
||||||
|
string = String(string);
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iteration utility for arrays and objects.
|
||||||
|
* @private
|
||||||
|
* @param {Array|Object} object The object to iterate over.
|
||||||
|
* @param {Function} callback The function called per iteration.
|
||||||
|
*/
|
||||||
|
function each(object, callback) {
|
||||||
|
var index = -1,
|
||||||
|
length = object.length;
|
||||||
|
|
||||||
|
if (length == length >>> 0) {
|
||||||
|
while (++index < length) {
|
||||||
|
callback(object[index], index, object);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
forOwn(object, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over an object's own properties, executing the `callback` for each.
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to iterate over.
|
||||||
|
* @param {Function} callback The function executed per own property.
|
||||||
|
*/
|
||||||
|
function forOwn(object, callback) {
|
||||||
|
for (var key in object) {
|
||||||
|
hasKey(object, key) && callback(object[key], key, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim and conditionally capitalize string values.
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to format.
|
||||||
|
* @returns {String} The formatted string.
|
||||||
|
*/
|
||||||
|
function format(string) {
|
||||||
|
string = trim(string);
|
||||||
|
return /^(?:webOS|i(?:OS|P))/.test(string)
|
||||||
|
? string
|
||||||
|
: capitalize(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal [[Class]] of a value.
|
||||||
|
* @private
|
||||||
|
* @param {Mixed} value The value.
|
||||||
|
* @returns {String} The [[Class]].
|
||||||
|
*/
|
||||||
|
function getClassOf(value) {
|
||||||
|
return value == null
|
||||||
|
? capitalize(value)
|
||||||
|
: toString.call(value).slice(8, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an object has the specified key as a direct property.
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to check.
|
||||||
|
* @param {String} key The key to check for.
|
||||||
|
* @returns {Boolean} Returns `true` if key is a direct property, else `false`.
|
||||||
|
*/
|
||||||
|
function hasKey() {
|
||||||
|
// lazy define for others (not as accurate)
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
var parent = object != null && (object.constructor || Object).prototype;
|
||||||
|
return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
|
||||||
|
};
|
||||||
|
// for modern browsers
|
||||||
|
if (getClassOf(hasOwnProperty) == 'Function') {
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
return object != null && hasOwnProperty.call(object, key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// for Safari 2
|
||||||
|
else if ({}.__proto__ == Object.prototype) {
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
var result = false;
|
||||||
|
if (object != null) {
|
||||||
|
object = Object(object);
|
||||||
|
object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return hasKey.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host objects can return type values that are different from their actual
|
||||||
|
* data type. The objects we are concerned with usually return non-primitive
|
||||||
|
* types of object, function, or unknown.
|
||||||
|
* @private
|
||||||
|
* @param {Mixed} object The owner of the property.
|
||||||
|
* @param {String} property The property to check.
|
||||||
|
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
|
||||||
|
*/
|
||||||
|
function isHostType(object, property) {
|
||||||
|
var type = object != null ? typeof object[property] : 'number';
|
||||||
|
return !/^(?:boolean|number|string|undefined)$/.test(type) &&
|
||||||
|
(type == 'object' ? !!object[property] : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bare-bones` Array#reduce` utility function.
|
||||||
|
* @private
|
||||||
|
* @param {Array} array The array to iterate over.
|
||||||
|
* @param {Function} callback The function called per iteration.
|
||||||
|
* @param {Mixed} accumulator Initial value of the accumulator.
|
||||||
|
* @returns {Mixed} The accumulator.
|
||||||
|
*/
|
||||||
|
function reduce(array, callback) {
|
||||||
|
var accumulator = null;
|
||||||
|
each(array, function(value, index) {
|
||||||
|
accumulator = callback(accumulator, value, index, array);
|
||||||
|
});
|
||||||
|
return accumulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a string for use in a RegExp constructor by making hyphens and spaces optional.
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to qualify.
|
||||||
|
* @returns {String} The qualified string.
|
||||||
|
*/
|
||||||
|
function qualify(string) {
|
||||||
|
return String(string).replace(/([ -])(?!$)/g, '$1?');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes leading and trailing whitespace from a string.
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to trim.
|
||||||
|
* @returns {String} The trimmed string.
|
||||||
|
*/
|
||||||
|
function trim(string) {
|
||||||
|
return String(string).replace(/^ +| +$/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new platform object.
|
||||||
|
* @memberOf platform
|
||||||
|
* @param {String} [ua = navigator.userAgent] The user agent string.
|
||||||
|
* @returns {Object} A platform object.
|
||||||
|
*/
|
||||||
|
function parse(ua) {
|
||||||
|
|
||||||
|
ua || (ua = userAgent);
|
||||||
|
|
||||||
|
/** Temporary variable used over the script's lifetime */
|
||||||
|
var data,
|
||||||
|
|
||||||
|
/** The CPU architecture */
|
||||||
|
arch = ua,
|
||||||
|
|
||||||
|
/** Platform description array */
|
||||||
|
description = [],
|
||||||
|
|
||||||
|
/** Platform alpha/beta indicator */
|
||||||
|
prerelease = null,
|
||||||
|
|
||||||
|
/** A flag to indicate that environment features should be used to resolve the platform */
|
||||||
|
useFeatures = ua == userAgent,
|
||||||
|
|
||||||
|
/** The browser/environment version */
|
||||||
|
version = useFeatures && opera && typeof opera.version == 'function' && opera.version(),
|
||||||
|
|
||||||
|
/* Detectable layout engines (order is important) */
|
||||||
|
layout = getLayout([
|
||||||
|
{ 'label': 'WebKit', 'pattern': 'AppleWebKit' },
|
||||||
|
'iCab',
|
||||||
|
'Presto',
|
||||||
|
'NetFront',
|
||||||
|
'Tasman',
|
||||||
|
'Trident',
|
||||||
|
'KHTML',
|
||||||
|
'Gecko'
|
||||||
|
]),
|
||||||
|
|
||||||
|
/* Detectable browser names (order is important) */
|
||||||
|
name = getName([
|
||||||
|
'Adobe AIR',
|
||||||
|
'Arora',
|
||||||
|
'Avant Browser',
|
||||||
|
'Camino',
|
||||||
|
'Epiphany',
|
||||||
|
'Fennec',
|
||||||
|
'Flock',
|
||||||
|
'Galeon',
|
||||||
|
'GreenBrowser',
|
||||||
|
'iCab',
|
||||||
|
'Iceweasel',
|
||||||
|
'Iron',
|
||||||
|
'K-Meleon',
|
||||||
|
'Konqueror',
|
||||||
|
'Lunascape',
|
||||||
|
'Maxthon',
|
||||||
|
'Midori',
|
||||||
|
'Nook Browser',
|
||||||
|
'PhantomJS',
|
||||||
|
'Raven',
|
||||||
|
'Rekonq',
|
||||||
|
'RockMelt',
|
||||||
|
'SeaMonkey',
|
||||||
|
{ 'label': 'Silk', 'pattern': '(?:Cloud9|Silk)' },
|
||||||
|
'Sleipnir',
|
||||||
|
'SlimBrowser',
|
||||||
|
'Sunrise',
|
||||||
|
'Swiftfox',
|
||||||
|
'WebPositive',
|
||||||
|
'Opera Mini',
|
||||||
|
'Opera',
|
||||||
|
'Chrome',
|
||||||
|
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
|
||||||
|
{ 'label': 'IE', 'pattern': 'MSIE' },
|
||||||
|
'Safari'
|
||||||
|
]),
|
||||||
|
|
||||||
|
/* Detectable products (order is important) */
|
||||||
|
product = getProduct([
|
||||||
|
'BlackBerry',
|
||||||
|
{ 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
|
||||||
|
{ 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
|
||||||
|
'iPad',
|
||||||
|
'iPod',
|
||||||
|
'iPhone',
|
||||||
|
'Kindle',
|
||||||
|
{ 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk)' },
|
||||||
|
'Nook',
|
||||||
|
'PlayBook',
|
||||||
|
'TouchPad',
|
||||||
|
'Transformer',
|
||||||
|
'Xoom'
|
||||||
|
]),
|
||||||
|
|
||||||
|
/* Detectable manufacturers */
|
||||||
|
manufacturer = getManufacturer({
|
||||||
|
'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
|
||||||
|
'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
|
||||||
|
'Asus': { 'Transformer': 1 },
|
||||||
|
'Barnes & Noble': { 'Nook': 1 },
|
||||||
|
'BlackBerry': { 'PlayBook': 1 },
|
||||||
|
'HP': { 'TouchPad': 1 },
|
||||||
|
'LG': { },
|
||||||
|
'Motorola': { 'Xoom': 1 },
|
||||||
|
'Nokia': { },
|
||||||
|
'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 }
|
||||||
|
}),
|
||||||
|
|
||||||
|
/* Detectable OSes (order is important) */
|
||||||
|
os = getOS([
|
||||||
|
'Android',
|
||||||
|
'CentOS',
|
||||||
|
'Debian',
|
||||||
|
'Fedora',
|
||||||
|
'FreeBSD',
|
||||||
|
'Gentoo',
|
||||||
|
'Haiku',
|
||||||
|
'Kubuntu',
|
||||||
|
'Linux Mint',
|
||||||
|
'Red Hat',
|
||||||
|
'SuSE',
|
||||||
|
'Ubuntu',
|
||||||
|
'Xubuntu',
|
||||||
|
'Cygwin',
|
||||||
|
'Symbian OS',
|
||||||
|
'hpwOS',
|
||||||
|
'webOS ',
|
||||||
|
'webOS',
|
||||||
|
'Tablet OS',
|
||||||
|
'Linux',
|
||||||
|
'Mac OS X',
|
||||||
|
'Macintosh',
|
||||||
|
'Mac',
|
||||||
|
'Windows 98;',
|
||||||
|
'Windows '
|
||||||
|
]);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the layout engine from an array of guesses.
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected layout engine.
|
||||||
|
*/
|
||||||
|
function getLayout(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
return result || RegExp('\\b' + (
|
||||||
|
guess.pattern || qualify(guess)
|
||||||
|
) + '\\b', 'i').exec(ua) && (guess.label || guess);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the manufacturer from an array of guesses.
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected manufacturer.
|
||||||
|
*/
|
||||||
|
function getManufacturer(guesses) {
|
||||||
|
return reduce(guesses, function(result, value, key) {
|
||||||
|
// lookup the manufacturer by product or scan the UA for the manufacturer
|
||||||
|
return result || (
|
||||||
|
value[product] ||
|
||||||
|
value[0/*Opera 9.25 fix*/, /^[a-z]+/i.exec(product)] ||
|
||||||
|
RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
|
||||||
|
) && (key.label || key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the browser name from an array of guesses.
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected browser name.
|
||||||
|
*/
|
||||||
|
function getName(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
return result || RegExp('\\b' + (
|
||||||
|
guess.pattern || qualify(guess)
|
||||||
|
) + '\\b', 'i').exec(ua) && (guess.label || guess);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the OS name from an array of guesses.
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected OS name.
|
||||||
|
*/
|
||||||
|
function getOS(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
var pattern = guess.pattern || qualify(guess);
|
||||||
|
if (!result && (result =
|
||||||
|
RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) {
|
||||||
|
// platform tokens defined at
|
||||||
|
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
||||||
|
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
||||||
|
data = {
|
||||||
|
'6.2': '8',
|
||||||
|
'6.1': 'Server 2008 R2 / 7',
|
||||||
|
'6.0': 'Server 2008 / Vista',
|
||||||
|
'5.2': 'Server 2003 / XP 64-bit',
|
||||||
|
'5.1': 'XP',
|
||||||
|
'5.01': '2000 SP1',
|
||||||
|
'5.0': '2000',
|
||||||
|
'4.0': 'NT',
|
||||||
|
'4.90': 'ME'
|
||||||
|
};
|
||||||
|
// detect Windows version from platform tokens
|
||||||
|
if (/^Win/i.test(result) &&
|
||||||
|
(data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) {
|
||||||
|
result = 'Windows ' + data;
|
||||||
|
}
|
||||||
|
// correct character case and cleanup
|
||||||
|
result = format(String(result)
|
||||||
|
.replace(RegExp(pattern, 'i'), guess.label || guess)
|
||||||
|
.replace(/ ce$/i, ' CE')
|
||||||
|
.replace(/hpw/i, 'web')
|
||||||
|
.replace(/Macintosh/, 'Mac OS')
|
||||||
|
.replace(/_PowerPC/i, ' OS')
|
||||||
|
.replace(/(OS X) [^ \d]+/i, '$1')
|
||||||
|
.replace(/\/(\d)/, ' $1')
|
||||||
|
.replace(/_/g, '.')
|
||||||
|
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
|
||||||
|
.replace(/x86\.64/gi, 'x86_64')
|
||||||
|
.split(' on ')[0]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the product name from an array of guesses.
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected product name.
|
||||||
|
*/
|
||||||
|
function getProduct(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
var pattern = guess.pattern || qualify(guess);
|
||||||
|
if (!result && (result =
|
||||||
|
RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
|
||||||
|
RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
|
||||||
|
)) {
|
||||||
|
// split by forward slash and append product version if needed
|
||||||
|
if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
|
||||||
|
result[0] += ' ' + result[1];
|
||||||
|
}
|
||||||
|
// correct character case and cleanup
|
||||||
|
guess = guess.label || guess;
|
||||||
|
result = format(result[0]
|
||||||
|
.replace(RegExp(pattern, 'i'), guess)
|
||||||
|
.replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
|
||||||
|
.replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2'));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the version using an array of UA patterns.
|
||||||
|
* @private
|
||||||
|
* @param {Array} patterns An array of UA patterns.
|
||||||
|
* @returns {String|Null} The detected version.
|
||||||
|
*/
|
||||||
|
function getVersion(patterns) {
|
||||||
|
return reduce(patterns, function(result, pattern) {
|
||||||
|
return result || (RegExp(pattern +
|
||||||
|
'(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/-]*)', 'i').exec(ua) || 0)[1] || null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores a previously overwritten platform object.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type Function
|
||||||
|
* @returns {Object} The current platform object.
|
||||||
|
*/
|
||||||
|
function noConflict() {
|
||||||
|
window['platform'] = old;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return platform description when the platform object is coerced to a string.
|
||||||
|
* @name toString
|
||||||
|
* @memberOf platform
|
||||||
|
* @type Function
|
||||||
|
* @returns {String} The platform description.
|
||||||
|
*/
|
||||||
|
function toStringPlatform() {
|
||||||
|
return this.description || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// convert layout to an array so we can add extra details
|
||||||
|
layout && (layout = [layout]);
|
||||||
|
|
||||||
|
// detect product names that contain their manufacturer's name
|
||||||
|
if (manufacturer && !product) {
|
||||||
|
product = getProduct([manufacturer]);
|
||||||
|
}
|
||||||
|
// detect simulators
|
||||||
|
if (/\bSimulator\b/i.test(ua)) {
|
||||||
|
product = (product ? product + ' ' : '') + 'Simulator';
|
||||||
|
}
|
||||||
|
// detect iOS
|
||||||
|
if (/^iP/.test(product)) {
|
||||||
|
name || (name = 'Safari');
|
||||||
|
os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
|
||||||
|
? ' ' + data[1].replace(/_/g, '.')
|
||||||
|
: '');
|
||||||
|
}
|
||||||
|
// detect Kubuntu
|
||||||
|
else if (name == 'Konqueror' && !/buntu/i.test(os)) {
|
||||||
|
os = 'Kubuntu';
|
||||||
|
}
|
||||||
|
// detect Android browsers
|
||||||
|
else if (name == 'Chrome' && manufacturer) {
|
||||||
|
name = 'Android Browser';
|
||||||
|
os = /Android/.test(os) ? os : 'Android';
|
||||||
|
}
|
||||||
|
// detect false positives for Firefox/Safari
|
||||||
|
else if (!name || (data = !/\bMinefield\b/i.test(ua) && /Firefox|Safari/.exec(name))) {
|
||||||
|
// clear name of false positives
|
||||||
|
if (name && !product && /[/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
|
||||||
|
name = null;
|
||||||
|
}
|
||||||
|
// reassign a generic name
|
||||||
|
if ((data = product || manufacturer || os) &&
|
||||||
|
(product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) {
|
||||||
|
name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect non-Opera versions (order is important)
|
||||||
|
if (!version) {
|
||||||
|
version = getVersion([
|
||||||
|
'(?:Cloud9|Opera ?Mini|Raven|Silk)',
|
||||||
|
'Version',
|
||||||
|
qualify(name),
|
||||||
|
'(?:Firefox|Minefield|NetFront)'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// detect stubborn layout engines
|
||||||
|
if (layout == 'iCab' && parseFloat(version) > 3) {
|
||||||
|
layout = ['WebKit'];
|
||||||
|
} else if (name == 'Konqueror' && /\bKHTML\b/i.test(ua)) {
|
||||||
|
layout = ['KHTML'];
|
||||||
|
} else if (data =
|
||||||
|
/Opera/.test(name) && 'Presto' ||
|
||||||
|
/\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
|
||||||
|
!layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) {
|
||||||
|
layout = [data];
|
||||||
|
}
|
||||||
|
// leverage environment features
|
||||||
|
if (useFeatures) {
|
||||||
|
// detect server-side environments
|
||||||
|
// Rhino has a global function while others have a global object
|
||||||
|
if (isHostType(thisBinding, 'global')) {
|
||||||
|
if (java) {
|
||||||
|
data = java.lang.System;
|
||||||
|
arch = data.getProperty('os.arch');
|
||||||
|
os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
|
||||||
|
}
|
||||||
|
if (typeof exports == 'object' && exports) {
|
||||||
|
// if `thisBinding` is the [ModuleScope]
|
||||||
|
if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
|
||||||
|
os || (os = data[0].os || null);
|
||||||
|
try {
|
||||||
|
data[1] = require('ringo/engine').version;
|
||||||
|
version = data[1].join('.');
|
||||||
|
name = 'RingoJS';
|
||||||
|
} catch(e) {
|
||||||
|
if (data[0].global == freeGlobal) {
|
||||||
|
name = 'Narwhal';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof process == 'object' && (data = process)) {
|
||||||
|
name = 'Node.js';
|
||||||
|
arch = data.arch;
|
||||||
|
os = data.platform;
|
||||||
|
version = /[\d.]+/.exec(data.version)[0];
|
||||||
|
}
|
||||||
|
} else if (getClassOf(window.environment) == 'Environment') {
|
||||||
|
name = 'Rhino';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Adobe AIR
|
||||||
|
else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') {
|
||||||
|
name = 'Adobe AIR';
|
||||||
|
os = data.flash.system.Capabilities.os;
|
||||||
|
}
|
||||||
|
// detect PhantomJS
|
||||||
|
else if (getClassOf(data = window.phantom) == 'RuntimeObject') {
|
||||||
|
name = 'PhantomJS';
|
||||||
|
version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
|
||||||
|
}
|
||||||
|
// detect IE compatibility modes
|
||||||
|
else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
|
||||||
|
// we're in compatibility mode when the Trident version + 4 doesn't
|
||||||
|
// equal the document mode
|
||||||
|
version = [version, doc.documentMode];
|
||||||
|
if ((data = +data[1] + 4) != version[1]) {
|
||||||
|
description.push('IE ' + version[1] + ' mode');
|
||||||
|
layout[1] = '';
|
||||||
|
version[1] = data;
|
||||||
|
}
|
||||||
|
version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
|
||||||
|
}
|
||||||
|
os = os && format(os);
|
||||||
|
}
|
||||||
|
// detect prerelease phases
|
||||||
|
if (version && (data =
|
||||||
|
/(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
|
||||||
|
/(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
|
||||||
|
/\bMinefield\b/i.test(ua) && 'a')) {
|
||||||
|
prerelease = /b/i.test(data) ? 'beta' : 'alpha';
|
||||||
|
version = version.replace(RegExp(data + '\\+?$'), '') +
|
||||||
|
(prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
|
||||||
|
}
|
||||||
|
// obscure Maxthon's unreliable version
|
||||||
|
if (name == 'Maxthon' && version) {
|
||||||
|
version = version.replace(/\.[\d.]+/, '.x');
|
||||||
|
}
|
||||||
|
// detect Silk desktop/accelerated modes
|
||||||
|
else if (name == 'Silk') {
|
||||||
|
if (!/Mobi/i.test(ua)) {
|
||||||
|
os = 'Android';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
}
|
||||||
|
if (/Accelerated *= *true/i.test(ua)) {
|
||||||
|
description.unshift('accelerated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Windows Phone desktop mode
|
||||||
|
else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
|
||||||
|
name += ' Mobile';
|
||||||
|
os = 'Windows Phone OS ' + data + '.x';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
}
|
||||||
|
// add mobile postfix
|
||||||
|
else if ((name == 'IE' || name && !product && !/Browser/.test(name)) &&
|
||||||
|
(os == 'Windows CE' || /Mobi/i.test(ua))) {
|
||||||
|
name += ' Mobile';
|
||||||
|
}
|
||||||
|
// detect IE platform preview
|
||||||
|
else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) {
|
||||||
|
description.unshift('platform preview');
|
||||||
|
}
|
||||||
|
// detect BlackBerry OS version
|
||||||
|
// http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
|
||||||
|
else if (/BlackBerry/.test(product) && (data =
|
||||||
|
(RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
|
||||||
|
version)) {
|
||||||
|
os = 'Device Software ' + data;
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
// detect Opera identifying/masking itself as another browser
|
||||||
|
// http://www.opera.com/support/kb/view/843/
|
||||||
|
else if (this != forOwn && (
|
||||||
|
(useFeatures && opera) ||
|
||||||
|
(/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
|
||||||
|
(name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) ||
|
||||||
|
(name == 'IE' && (
|
||||||
|
(os && !/^Win/.test(os) && version > 5.5) ||
|
||||||
|
/Windows XP/.test(os) && version > 8 ||
|
||||||
|
version == 8 && !/Trident/.test(ua)
|
||||||
|
))
|
||||||
|
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
|
||||||
|
|
||||||
|
// when "indentifying" the UA contains both Opera and the other browser's name
|
||||||
|
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
|
||||||
|
if (reOpera.test(name)) {
|
||||||
|
if (/IE/.test(data) && os == 'Mac OS') {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
data = 'identify' + data;
|
||||||
|
}
|
||||||
|
// when "masking" the UA contains only the other browser's name
|
||||||
|
else {
|
||||||
|
data = 'mask' + data;
|
||||||
|
if (operaClass) {
|
||||||
|
name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
|
||||||
|
} else {
|
||||||
|
name = 'Opera';
|
||||||
|
}
|
||||||
|
if (/IE/.test(data)) {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
if (!useFeatures) {
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout = ['Presto'];
|
||||||
|
description.push(data);
|
||||||
|
}
|
||||||
|
// detect WebKit Nightly and approximate Chrome/Safari versions
|
||||||
|
if ((data = (/AppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
|
||||||
|
// nightly builds are postfixed with a `+`
|
||||||
|
data = [parseFloat(data), data];
|
||||||
|
if (name == 'Safari' && data[1].slice(-1) == '+') {
|
||||||
|
name = 'WebKit Nightly';
|
||||||
|
prerelease = 'alpha';
|
||||||
|
version = data[1].slice(0, -1);
|
||||||
|
}
|
||||||
|
// clear incorrect browser versions
|
||||||
|
else if (version == data[1] ||
|
||||||
|
version == (/Safari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) {
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
// use the full Chrome version when available
|
||||||
|
data = [data[0], (/Chrome\/([\d.]+)/i.exec(ua) || 0)[1]];
|
||||||
|
|
||||||
|
// detect JavaScriptCore
|
||||||
|
// http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
|
||||||
|
if (!useFeatures || (/internal|\n/i.test(toString.toString()) && !data[1])) {
|
||||||
|
layout[1] = 'like Safari';
|
||||||
|
data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
|
||||||
|
} else {
|
||||||
|
layout[1] = 'like Chrome';
|
||||||
|
data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.5 ? 3 : data < 533 ? 4 : data < 534.3 ? 5 : data < 534.7 ? 6 : data < 534.1 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.3 ? 11 : data < 535.1 ? 12 : data < 535.2 ? '13+' : data < 535.5 ? 15 : data < 535.7 ? 16 : '17');
|
||||||
|
}
|
||||||
|
// add the postfix of ".x" or "+" for approximate versions
|
||||||
|
layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
|
||||||
|
// obscure version for some Safari 1-2 releases
|
||||||
|
if (name == 'Safari' && (!version || parseInt(version) > 45)) {
|
||||||
|
version = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// strip incorrect OS versions
|
||||||
|
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
|
||||||
|
ua.indexOf('/' + data + '-') > -1) {
|
||||||
|
os = trim(os.replace(data, ''));
|
||||||
|
}
|
||||||
|
// add layout engine
|
||||||
|
if (layout && !/Avant|Nook/.test(name) && (
|
||||||
|
/Browser|Lunascape|Maxthon/.test(name) ||
|
||||||
|
/^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) {
|
||||||
|
// don't add layout details to description if they are falsey
|
||||||
|
(data = layout[layout.length - 1]) && description.push(data);
|
||||||
|
}
|
||||||
|
// combine contextual information
|
||||||
|
if (description.length) {
|
||||||
|
description = ['(' + description.join('; ') + ')'];
|
||||||
|
}
|
||||||
|
// append manufacturer
|
||||||
|
if (manufacturer && product && product.indexOf(manufacturer) < 0) {
|
||||||
|
description.push('on ' + manufacturer);
|
||||||
|
}
|
||||||
|
// append product
|
||||||
|
if (product) {
|
||||||
|
description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
|
||||||
|
}
|
||||||
|
// add browser/OS architecture
|
||||||
|
if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i).test(arch) && !/\bi686\b/i.test(arch)) {
|
||||||
|
os = os && os + (data.test(os) ? '' : ' 64-bit');
|
||||||
|
if (name && (/WOW64/i.test(ua) ||
|
||||||
|
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
|
||||||
|
description.unshift('32-bit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ua || (ua = null);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform object.
|
||||||
|
* @name platform
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
return {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The browser/environment version.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'version': name && version && (description.unshift(version), version),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the browser/environment.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'name': name && (description.unshift(name), name),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the operating system.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'os': os && (name &&
|
||||||
|
!(os == os.split(' ')[0] && (os == name.split(' ')[0] || product)) &&
|
||||||
|
description.push(product ? '(' + os + ')' : 'on ' + os), os),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform description.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'description': description.length ? description.join(' ') : ua,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the browser layout engine.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'layout': layout && layout[0],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the product's manufacturer.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'manufacturer': manufacturer,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The alpha/beta release indicator.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'prerelease': prerelease,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the product hosting the browser.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'product': product,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The browser's user agent string.
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'ua': ua,
|
||||||
|
|
||||||
|
// avoid platform object conflicts in browsers
|
||||||
|
'noConflict': noConflict,
|
||||||
|
|
||||||
|
// parses a user agent string into a platform object
|
||||||
|
'parse': parse,
|
||||||
|
|
||||||
|
// returns the platform description
|
||||||
|
'toString': toStringPlatform
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// expose platform
|
||||||
|
// in Narwhal, Node.js, or RingoJS
|
||||||
|
if (freeExports) {
|
||||||
|
forOwn(parse(), function(value, key) {
|
||||||
|
freeExports[key] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// via curl.js or RequireJS
|
||||||
|
else if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
|
||||||
|
define('platform', function() {
|
||||||
|
return parse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// in a browser or Rhino
|
||||||
|
else {
|
||||||
|
// use square bracket notation so Closure Compiler won't munge `platform`
|
||||||
|
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||||
|
window['platform'] = parse();
|
||||||
|
}
|
||||||
|
}(this));
|
4874
node_modules/esprima/test/3rdparty/prototype-1.6.1.js
generated
vendored
Normal file
4874
node_modules/esprima/test/3rdparty/prototype-1.6.1.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6082
node_modules/esprima/test/3rdparty/prototype-1.7.0.0.js
generated
vendored
Normal file
6082
node_modules/esprima/test/3rdparty/prototype-1.7.0.0.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
981
node_modules/esprima/test/3rdparty/underscore-1.2.3.js
generated
vendored
Normal file
981
node_modules/esprima/test/3rdparty/underscore-1.2.3.js
generated
vendored
Normal file
@ -0,0 +1,981 @@
|
|||||||
|
// Underscore.js 1.2.3
|
||||||
|
// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
|
// Underscore is freely distributable under the MIT license.
|
||||||
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||||
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||||
|
// For all details and documentation:
|
||||||
|
// http://documentcloud.github.com/underscore
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
// Baseline setup
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||||
|
var root = this;
|
||||||
|
|
||||||
|
// Save the previous value of the `_` variable.
|
||||||
|
var previousUnderscore = root._;
|
||||||
|
|
||||||
|
// Establish the object that gets returned to break out of a loop iteration.
|
||||||
|
var breaker = {};
|
||||||
|
|
||||||
|
// Save bytes in the minified (but not gzipped) version:
|
||||||
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||||||
|
|
||||||
|
// Create quick reference variables for speed access to core prototypes.
|
||||||
|
var slice = ArrayProto.slice,
|
||||||
|
concat = ArrayProto.concat,
|
||||||
|
unshift = ArrayProto.unshift,
|
||||||
|
toString = ObjProto.toString,
|
||||||
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||||
|
|
||||||
|
// All **ECMAScript 5** native function implementations that we hope to use
|
||||||
|
// are declared here.
|
||||||
|
var
|
||||||
|
nativeForEach = ArrayProto.forEach,
|
||||||
|
nativeMap = ArrayProto.map,
|
||||||
|
nativeReduce = ArrayProto.reduce,
|
||||||
|
nativeReduceRight = ArrayProto.reduceRight,
|
||||||
|
nativeFilter = ArrayProto.filter,
|
||||||
|
nativeEvery = ArrayProto.every,
|
||||||
|
nativeSome = ArrayProto.some,
|
||||||
|
nativeIndexOf = ArrayProto.indexOf,
|
||||||
|
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||||||
|
nativeIsArray = Array.isArray,
|
||||||
|
nativeKeys = Object.keys,
|
||||||
|
nativeBind = FuncProto.bind;
|
||||||
|
|
||||||
|
// Create a safe reference to the Underscore object for use below.
|
||||||
|
var _ = function(obj) { return new wrapper(obj); };
|
||||||
|
|
||||||
|
// Export the Underscore object for **Node.js** and **"CommonJS"**, with
|
||||||
|
// backwards-compatibility for the old `require()` API. If we're not in
|
||||||
|
// CommonJS, add `_` to the global object.
|
||||||
|
if (typeof exports !== 'undefined') {
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
exports = module.exports = _;
|
||||||
|
}
|
||||||
|
exports._ = _;
|
||||||
|
} else if (typeof define === 'function' && define.amd) {
|
||||||
|
// Register as a named module with AMD.
|
||||||
|
define('underscore', function() {
|
||||||
|
return _;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Exported as a string, for Closure Compiler "advanced" mode.
|
||||||
|
root['_'] = _;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current version.
|
||||||
|
_.VERSION = '1.2.3';
|
||||||
|
|
||||||
|
// Collection Functions
|
||||||
|
// --------------------
|
||||||
|
|
||||||
|
// The cornerstone, an `each` implementation, aka `forEach`.
|
||||||
|
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||||
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||||
|
if (obj == null) return;
|
||||||
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||||
|
obj.forEach(iterator, context);
|
||||||
|
} else if (obj.length === +obj.length) {
|
||||||
|
for (var i = 0, l = obj.length; i < l; i++) {
|
||||||
|
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var key in obj) {
|
||||||
|
if (hasOwnProperty.call(obj, key)) {
|
||||||
|
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the results of applying the iterator to each element.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||||
|
_.map = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
results[results.length] = iterator.call(context, value, index, list);
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||||
|
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||||
|
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||||
|
var initial = arguments.length > 2;
|
||||||
|
if (obj == null) obj = [];
|
||||||
|
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||||
|
}
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!initial) {
|
||||||
|
memo = value;
|
||||||
|
initial = true;
|
||||||
|
} else {
|
||||||
|
memo = iterator.call(context, memo, value, index, list);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||||
|
return memo;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The right-associative version of reduce, also known as `foldr`.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||||
|
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||||
|
var initial = arguments.length > 2;
|
||||||
|
if (obj == null) obj = [];
|
||||||
|
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||||
|
}
|
||||||
|
var reversed = _.toArray(obj).reverse();
|
||||||
|
if (context && !initial) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||||
|
_.find = _.detect = function(obj, iterator, context) {
|
||||||
|
var result;
|
||||||
|
any(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) {
|
||||||
|
result = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements that pass a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||||
|
// Aliased as `select`.
|
||||||
|
_.filter = _.select = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements for which a truth test fails.
|
||||||
|
_.reject = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine whether all of the elements match a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||||
|
// Aliased as `all`.
|
||||||
|
_.every = _.all = function(obj, iterator, context) {
|
||||||
|
var result = true;
|
||||||
|
if (obj == null) return result;
|
||||||
|
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if at least one element in the object matches a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||||
|
// Aliased as `any`.
|
||||||
|
var any = _.some = _.any = function(obj, iterator, context) {
|
||||||
|
iterator || (iterator = _.identity);
|
||||||
|
var result = false;
|
||||||
|
if (obj == null) return result;
|
||||||
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
||||||
|
});
|
||||||
|
return !!result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if a given value is included in the array or object using `===`.
|
||||||
|
// Aliased as `contains`.
|
||||||
|
_.include = _.contains = function(obj, target) {
|
||||||
|
var found = false;
|
||||||
|
if (obj == null) return found;
|
||||||
|
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||||
|
found = any(obj, function(value) {
|
||||||
|
return value === target;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke a method (with arguments) on every item in a collection.
|
||||||
|
_.invoke = function(obj, method) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return _.map(obj, function(value) {
|
||||||
|
return (method.call ? method || value : value[method]).apply(value, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience version of a common use case of `map`: fetching a property.
|
||||||
|
_.pluck = function(obj, key) {
|
||||||
|
return _.map(obj, function(value){ return value[key]; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the maximum element or (element-based computation).
|
||||||
|
_.max = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||||
|
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||||
|
var result = {computed : -Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed >= result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the minimum element (or element-based computation).
|
||||||
|
_.min = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||||
|
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||||
|
var result = {computed : Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed < result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shuffle an array.
|
||||||
|
_.shuffle = function(obj) {
|
||||||
|
var shuffled = [], rand;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (index == 0) {
|
||||||
|
shuffled[0] = value;
|
||||||
|
} else {
|
||||||
|
rand = Math.floor(Math.random() * (index + 1));
|
||||||
|
shuffled[index] = shuffled[rand];
|
||||||
|
shuffled[rand] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return shuffled;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sort the object's values by a criterion produced by an iterator.
|
||||||
|
_.sortBy = function(obj, iterator, context) {
|
||||||
|
return _.pluck(_.map(obj, function(value, index, list) {
|
||||||
|
return {
|
||||||
|
value : value,
|
||||||
|
criteria : iterator.call(context, value, index, list)
|
||||||
|
};
|
||||||
|
}).sort(function(left, right) {
|
||||||
|
var a = left.criteria, b = right.criteria;
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
}), 'value');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Groups the object's values by a criterion. Pass either a string attribute
|
||||||
|
// to group by, or a function that returns the criterion.
|
||||||
|
_.groupBy = function(obj, val) {
|
||||||
|
var result = {};
|
||||||
|
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
||||||
|
each(obj, function(value, index) {
|
||||||
|
var key = iterator(value, index);
|
||||||
|
(result[key] || (result[key] = [])).push(value);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use a comparator function to figure out at what index an object should
|
||||||
|
// be inserted so as to maintain order. Uses binary search.
|
||||||
|
_.sortedIndex = function(array, obj, iterator) {
|
||||||
|
iterator || (iterator = _.identity);
|
||||||
|
var low = 0, high = array.length;
|
||||||
|
while (low < high) {
|
||||||
|
var mid = (low + high) >> 1;
|
||||||
|
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Safely convert anything iterable into a real, live array.
|
||||||
|
_.toArray = function(iterable) {
|
||||||
|
if (!iterable) return [];
|
||||||
|
if (iterable.toArray) return iterable.toArray();
|
||||||
|
if (_.isArray(iterable)) return slice.call(iterable);
|
||||||
|
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||||
|
return _.values(iterable);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the number of elements in an object.
|
||||||
|
_.size = function(obj) {
|
||||||
|
return _.toArray(obj).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Array Functions
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// Get the first element of an array. Passing **n** will return the first N
|
||||||
|
// values in the array. Aliased as `head`. The **guard** check allows it to work
|
||||||
|
// with `_.map`.
|
||||||
|
_.first = _.head = function(array, n, guard) {
|
||||||
|
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns everything but the last entry of the array. Especcialy useful on
|
||||||
|
// the arguments object. Passing **n** will return all the values in
|
||||||
|
// the array, excluding the last N. The **guard** check allows it to work with
|
||||||
|
// `_.map`.
|
||||||
|
_.initial = function(array, n, guard) {
|
||||||
|
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the last element of an array. Passing **n** will return the last N
|
||||||
|
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||||
|
_.last = function(array, n, guard) {
|
||||||
|
if ((n != null) && !guard) {
|
||||||
|
return slice.call(array, Math.max(array.length - n, 0));
|
||||||
|
} else {
|
||||||
|
return array[array.length - 1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns everything but the first entry of the array. Aliased as `tail`.
|
||||||
|
// Especially useful on the arguments object. Passing an **index** will return
|
||||||
|
// the rest of the values in the array from that index onward. The **guard**
|
||||||
|
// check allows it to work with `_.map`.
|
||||||
|
_.rest = _.tail = function(array, index, guard) {
|
||||||
|
return slice.call(array, (index == null) || guard ? 1 : index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trim out all falsy values from an array.
|
||||||
|
_.compact = function(array) {
|
||||||
|
return _.filter(array, function(value){ return !!value; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a completely flattened version of an array.
|
||||||
|
_.flatten = function(array, shallow) {
|
||||||
|
return _.reduce(array, function(memo, value) {
|
||||||
|
if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
|
||||||
|
memo[memo.length] = value;
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a version of the array that does not contain the specified value(s).
|
||||||
|
_.without = function(array) {
|
||||||
|
return _.difference(array, slice.call(arguments, 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce a duplicate-free version of the array. If the array has already
|
||||||
|
// been sorted, you have the option of using a faster algorithm.
|
||||||
|
// Aliased as `unique`.
|
||||||
|
_.uniq = _.unique = function(array, isSorted, iterator) {
|
||||||
|
var initial = iterator ? _.map(array, iterator) : array;
|
||||||
|
var result = [];
|
||||||
|
_.reduce(initial, function(memo, el, i) {
|
||||||
|
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
|
||||||
|
memo[memo.length] = el;
|
||||||
|
result[result.length] = array[i];
|
||||||
|
}
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce an array that contains the union: each distinct element from all of
|
||||||
|
// the passed-in arrays.
|
||||||
|
_.union = function() {
|
||||||
|
return _.uniq(_.flatten(arguments, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce an array that contains every item shared between all the
|
||||||
|
// passed-in arrays. (Aliased as "intersect" for back-compat.)
|
||||||
|
_.intersection = _.intersect = function(array) {
|
||||||
|
var rest = slice.call(arguments, 1);
|
||||||
|
return _.filter(_.uniq(array), function(item) {
|
||||||
|
return _.every(rest, function(other) {
|
||||||
|
return _.indexOf(other, item) >= 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Take the difference between one array and a number of other arrays.
|
||||||
|
// Only the elements present in just the first array will remain.
|
||||||
|
_.difference = function(array) {
|
||||||
|
var rest = _.flatten(slice.call(arguments, 1));
|
||||||
|
return _.filter(array, function(value){ return !_.include(rest, value); });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zip together multiple lists into a single array -- elements that share
|
||||||
|
// an index go together.
|
||||||
|
_.zip = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
var length = _.max(_.pluck(args, 'length'));
|
||||||
|
var results = new Array(length);
|
||||||
|
for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||||||
|
// we need this function. Return the position of the first occurrence of an
|
||||||
|
// item in an array, or -1 if the item is not included in the array.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||||
|
// If the array is large and already in sort order, pass `true`
|
||||||
|
// for **isSorted** to use binary search.
|
||||||
|
_.indexOf = function(array, item, isSorted) {
|
||||||
|
if (array == null) return -1;
|
||||||
|
var i, l;
|
||||||
|
if (isSorted) {
|
||||||
|
i = _.sortedIndex(array, item);
|
||||||
|
return array[i] === item ? i : -1;
|
||||||
|
}
|
||||||
|
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||||
|
for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||||
|
_.lastIndexOf = function(array, item) {
|
||||||
|
if (array == null) return -1;
|
||||||
|
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||||
|
var i = array.length;
|
||||||
|
while (i--) if (i in array && array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate an integer Array containing an arithmetic progression. A port of
|
||||||
|
// the native Python `range()` function. See
|
||||||
|
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||||||
|
_.range = function(start, stop, step) {
|
||||||
|
if (arguments.length <= 1) {
|
||||||
|
stop = start || 0;
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
step = arguments[2] || 1;
|
||||||
|
|
||||||
|
var len = Math.max(Math.ceil((stop - start) / step), 0);
|
||||||
|
var idx = 0;
|
||||||
|
var range = new Array(len);
|
||||||
|
|
||||||
|
while(idx < len) {
|
||||||
|
range[idx++] = start;
|
||||||
|
start += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function (ahem) Functions
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
// Reusable constructor function for prototype setting.
|
||||||
|
var ctor = function(){};
|
||||||
|
|
||||||
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||||
|
// optionally). Binding with arguments is also known as `curry`.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `Function.bind` if available.
|
||||||
|
// We check for `func.bind` first, to fail fast when `func` is undefined.
|
||||||
|
_.bind = function bind(func, context) {
|
||||||
|
var bound, args;
|
||||||
|
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||||||
|
if (!_.isFunction(func)) throw new TypeError;
|
||||||
|
args = slice.call(arguments, 2);
|
||||||
|
return bound = function() {
|
||||||
|
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||||||
|
ctor.prototype = func.prototype;
|
||||||
|
var self = new ctor;
|
||||||
|
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||||||
|
if (Object(result) === result) return result;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||||
|
// all callbacks defined on an object belong to it.
|
||||||
|
_.bindAll = function(obj) {
|
||||||
|
var funcs = slice.call(arguments, 1);
|
||||||
|
if (funcs.length == 0) funcs = _.functions(obj);
|
||||||
|
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memoize an expensive function by storing its results.
|
||||||
|
_.memoize = function(func, hasher) {
|
||||||
|
var memo = {};
|
||||||
|
hasher || (hasher = _.identity);
|
||||||
|
return function() {
|
||||||
|
var key = hasher.apply(this, arguments);
|
||||||
|
return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delays a function for the given number of milliseconds, and then calls
|
||||||
|
// it with the arguments supplied.
|
||||||
|
_.delay = function(func, wait) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defers a function, scheduling it to run after the current call stack has
|
||||||
|
// cleared.
|
||||||
|
_.defer = function(func) {
|
||||||
|
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function, that, when invoked, will only be triggered at most once
|
||||||
|
// during a given window of time.
|
||||||
|
_.throttle = function(func, wait) {
|
||||||
|
var context, args, timeout, throttling, more;
|
||||||
|
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||||
|
return function() {
|
||||||
|
context = this; args = arguments;
|
||||||
|
var later = function() {
|
||||||
|
timeout = null;
|
||||||
|
if (more) func.apply(context, args);
|
||||||
|
whenDone();
|
||||||
|
};
|
||||||
|
if (!timeout) timeout = setTimeout(later, wait);
|
||||||
|
if (throttling) {
|
||||||
|
more = true;
|
||||||
|
} else {
|
||||||
|
func.apply(context, args);
|
||||||
|
}
|
||||||
|
whenDone();
|
||||||
|
throttling = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function, that, as long as it continues to be invoked, will not
|
||||||
|
// be triggered. The function will be called after it stops being called for
|
||||||
|
// N milliseconds.
|
||||||
|
_.debounce = function(func, wait) {
|
||||||
|
var timeout;
|
||||||
|
return function() {
|
||||||
|
var context = this, args = arguments;
|
||||||
|
var later = function() {
|
||||||
|
timeout = null;
|
||||||
|
func.apply(context, args);
|
||||||
|
};
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that will be executed at most one time, no matter how
|
||||||
|
// often you call it. Useful for lazy initialization.
|
||||||
|
_.once = function(func) {
|
||||||
|
var ran = false, memo;
|
||||||
|
return function() {
|
||||||
|
if (ran) return memo;
|
||||||
|
ran = true;
|
||||||
|
return memo = func.apply(this, arguments);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the first function passed as an argument to the second,
|
||||||
|
// allowing you to adjust arguments, run code before and after, and
|
||||||
|
// conditionally execute the original function.
|
||||||
|
_.wrap = function(func, wrapper) {
|
||||||
|
return function() {
|
||||||
|
var args = concat.apply([func], arguments);
|
||||||
|
return wrapper.apply(this, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that is the composition of a list of functions, each
|
||||||
|
// consuming the return value of the function that follows.
|
||||||
|
_.compose = function() {
|
||||||
|
var funcs = arguments;
|
||||||
|
return function() {
|
||||||
|
var args = arguments;
|
||||||
|
for (var i = funcs.length - 1; i >= 0; i--) {
|
||||||
|
args = [funcs[i].apply(this, args)];
|
||||||
|
}
|
||||||
|
return args[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that will only be executed after being called N times.
|
||||||
|
_.after = function(times, func) {
|
||||||
|
if (times <= 0) return func();
|
||||||
|
return function() {
|
||||||
|
if (--times < 1) { return func.apply(this, arguments); }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Object Functions
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
// Retrieve the names of an object's properties.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||||
|
_.keys = nativeKeys || function(obj) {
|
||||||
|
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
||||||
|
var keys = [];
|
||||||
|
for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retrieve the values of an object's properties.
|
||||||
|
_.values = function(obj) {
|
||||||
|
return _.map(obj, _.identity);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a sorted list of the function names available on the object.
|
||||||
|
// Aliased as `methods`
|
||||||
|
_.functions = _.methods = function(obj) {
|
||||||
|
var names = [];
|
||||||
|
for (var key in obj) {
|
||||||
|
if (_.isFunction(obj[key])) names.push(key);
|
||||||
|
}
|
||||||
|
return names.sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extend a given object with all the properties in passed-in object(s).
|
||||||
|
_.extend = function(obj) {
|
||||||
|
each(slice.call(arguments, 1), function(source) {
|
||||||
|
for (var prop in source) {
|
||||||
|
if (source[prop] !== void 0) obj[prop] = source[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fill in a given object with default properties.
|
||||||
|
_.defaults = function(obj) {
|
||||||
|
each(slice.call(arguments, 1), function(source) {
|
||||||
|
for (var prop in source) {
|
||||||
|
if (obj[prop] == null) obj[prop] = source[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a (shallow-cloned) duplicate of an object.
|
||||||
|
_.clone = function(obj) {
|
||||||
|
if (!_.isObject(obj)) return obj;
|
||||||
|
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invokes interceptor with the obj, and then returns obj.
|
||||||
|
// The primary purpose of this method is to "tap into" a method chain, in
|
||||||
|
// order to perform operations on intermediate results within the chain.
|
||||||
|
_.tap = function(obj, interceptor) {
|
||||||
|
interceptor(obj);
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal recursive comparison function.
|
||||||
|
function eq(a, b, stack) {
|
||||||
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||||||
|
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
||||||
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||||
|
// A strict comparison is necessary because `null == undefined`.
|
||||||
|
if (a == null || b == null) return a === b;
|
||||||
|
// Unwrap any wrapped objects.
|
||||||
|
if (a._chain) a = a._wrapped;
|
||||||
|
if (b._chain) b = b._wrapped;
|
||||||
|
// Invoke a custom `isEqual` method if one is provided.
|
||||||
|
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
||||||
|
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
||||||
|
// Compare `[[Class]]` names.
|
||||||
|
var className = toString.call(a);
|
||||||
|
if (className != toString.call(b)) return false;
|
||||||
|
switch (className) {
|
||||||
|
// Strings, numbers, dates, and booleans are compared by value.
|
||||||
|
case '[object String]':
|
||||||
|
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||||||
|
// equivalent to `new String("5")`.
|
||||||
|
return a == String(b);
|
||||||
|
case '[object Number]':
|
||||||
|
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
||||||
|
// other numeric values.
|
||||||
|
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
|
||||||
|
case '[object Date]':
|
||||||
|
case '[object Boolean]':
|
||||||
|
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||||||
|
// millisecond representations. Note that invalid dates with millisecond representations
|
||||||
|
// of `NaN` are not equivalent.
|
||||||
|
return +a == +b;
|
||||||
|
// RegExps are compared by their source patterns and flags.
|
||||||
|
case '[object RegExp]':
|
||||||
|
return a.source == b.source &&
|
||||||
|
a.global == b.global &&
|
||||||
|
a.multiline == b.multiline &&
|
||||||
|
a.ignoreCase == b.ignoreCase;
|
||||||
|
}
|
||||||
|
if (typeof a != 'object' || typeof b != 'object') return false;
|
||||||
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||||||
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||||||
|
var length = stack.length;
|
||||||
|
while (length--) {
|
||||||
|
// Linear search. Performance is inversely proportional to the number of
|
||||||
|
// unique nested structures.
|
||||||
|
if (stack[length] == a) return true;
|
||||||
|
}
|
||||||
|
// Add the first object to the stack of traversed objects.
|
||||||
|
stack.push(a);
|
||||||
|
var size = 0, result = true;
|
||||||
|
// Recursively compare objects and arrays.
|
||||||
|
if (className == '[object Array]') {
|
||||||
|
// Compare array lengths to determine if a deep comparison is necessary.
|
||||||
|
size = a.length;
|
||||||
|
result = size == b.length;
|
||||||
|
if (result) {
|
||||||
|
// Deep compare the contents, ignoring non-numeric properties.
|
||||||
|
while (size--) {
|
||||||
|
// Ensure commutative equality for sparse arrays.
|
||||||
|
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Objects with different constructors are not equivalent.
|
||||||
|
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
||||||
|
// Deep compare objects.
|
||||||
|
for (var key in a) {
|
||||||
|
if (hasOwnProperty.call(a, key)) {
|
||||||
|
// Count the expected number of properties.
|
||||||
|
size++;
|
||||||
|
// Deep compare each member.
|
||||||
|
if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure that both objects contain the same number of properties.
|
||||||
|
if (result) {
|
||||||
|
for (key in b) {
|
||||||
|
if (hasOwnProperty.call(b, key) && !(size--)) break;
|
||||||
|
}
|
||||||
|
result = !size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the first object from the stack of traversed objects.
|
||||||
|
stack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a deep comparison to check if two objects are equal.
|
||||||
|
_.isEqual = function(a, b) {
|
||||||
|
return eq(a, b, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given array, string, or object empty?
|
||||||
|
// An "empty" object has no enumerable own-properties.
|
||||||
|
_.isEmpty = function(obj) {
|
||||||
|
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||||||
|
for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a DOM element?
|
||||||
|
_.isElement = function(obj) {
|
||||||
|
return !!(obj && obj.nodeType == 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value an array?
|
||||||
|
// Delegates to ECMA5's native Array.isArray
|
||||||
|
_.isArray = nativeIsArray || function(obj) {
|
||||||
|
return toString.call(obj) == '[object Array]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable an object?
|
||||||
|
_.isObject = function(obj) {
|
||||||
|
return obj === Object(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable an arguments object?
|
||||||
|
_.isArguments = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Arguments]';
|
||||||
|
};
|
||||||
|
if (!_.isArguments(arguments)) {
|
||||||
|
_.isArguments = function(obj) {
|
||||||
|
return !!(obj && hasOwnProperty.call(obj, 'callee'));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is a given value a function?
|
||||||
|
_.isFunction = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Function]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a string?
|
||||||
|
_.isString = function(obj) {
|
||||||
|
return toString.call(obj) == '[object String]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a number?
|
||||||
|
_.isNumber = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Number]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value `NaN`?
|
||||||
|
_.isNaN = function(obj) {
|
||||||
|
// `NaN` is the only value for which `===` is not reflexive.
|
||||||
|
return obj !== obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a boolean?
|
||||||
|
_.isBoolean = function(obj) {
|
||||||
|
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a date?
|
||||||
|
_.isDate = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Date]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value a regular expression?
|
||||||
|
_.isRegExp = function(obj) {
|
||||||
|
return toString.call(obj) == '[object RegExp]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value equal to null?
|
||||||
|
_.isNull = function(obj) {
|
||||||
|
return obj === null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable undefined?
|
||||||
|
_.isUndefined = function(obj) {
|
||||||
|
return obj === void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility Functions
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||||||
|
// previous owner. Returns a reference to the Underscore object.
|
||||||
|
_.noConflict = function() {
|
||||||
|
root._ = previousUnderscore;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep the identity function around for default iterators.
|
||||||
|
_.identity = function(value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run a function **n** times.
|
||||||
|
_.times = function (n, iterator, context) {
|
||||||
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Escape a string for HTML interpolation.
|
||||||
|
_.escape = function(string) {
|
||||||
|
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add your own custom functions to the Underscore object, ensuring that
|
||||||
|
// they're correctly added to the OOP wrapper as well.
|
||||||
|
_.mixin = function(obj) {
|
||||||
|
each(_.functions(obj), function(name){
|
||||||
|
addToWrapper(name, _[name] = obj[name]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a unique integer id (unique within the entire client session).
|
||||||
|
// Useful for temporary DOM ids.
|
||||||
|
var idCounter = 0;
|
||||||
|
_.uniqueId = function(prefix) {
|
||||||
|
var id = idCounter++;
|
||||||
|
return prefix ? prefix + id : id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// By default, Underscore uses ERB-style template delimiters, change the
|
||||||
|
// following template settings to use alternative delimiters.
|
||||||
|
_.templateSettings = {
|
||||||
|
evaluate : /<%([\s\S]+?)%>/g,
|
||||||
|
interpolate : /<%=([\s\S]+?)%>/g,
|
||||||
|
escape : /<%-([\s\S]+?)%>/g
|
||||||
|
};
|
||||||
|
|
||||||
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||||
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||||
|
// and correctly escapes quotes within interpolated code.
|
||||||
|
_.template = function(str, data) {
|
||||||
|
var c = _.templateSettings;
|
||||||
|
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
||||||
|
'with(obj||{}){__p.push(\'' +
|
||||||
|
str.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/'/g, "\\'")
|
||||||
|
.replace(c.escape, function(match, code) {
|
||||||
|
return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
|
||||||
|
})
|
||||||
|
.replace(c.interpolate, function(match, code) {
|
||||||
|
return "'," + code.replace(/\\'/g, "'") + ",'";
|
||||||
|
})
|
||||||
|
.replace(c.evaluate || null, function(match, code) {
|
||||||
|
return "');" + code.replace(/\\'/g, "'")
|
||||||
|
.replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
||||||
|
})
|
||||||
|
.replace(/\r/g, '\\r')
|
||||||
|
.replace(/\n/g, '\\n')
|
||||||
|
.replace(/\t/g, '\\t')
|
||||||
|
+ "');}return __p.join('');";
|
||||||
|
var func = new Function('obj', '_', tmpl);
|
||||||
|
if (data) return func(data, _);
|
||||||
|
return function(data) {
|
||||||
|
return func.call(this, data, _);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// The OOP Wrapper
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// If Underscore is called as a function, it returns a wrapped object that
|
||||||
|
// can be used OO-style. This wrapper holds altered versions of all the
|
||||||
|
// underscore functions. Wrapped objects may be chained.
|
||||||
|
var wrapper = function(obj) { this._wrapped = obj; };
|
||||||
|
|
||||||
|
// Expose `wrapper.prototype` as `_.prototype`
|
||||||
|
_.prototype = wrapper.prototype;
|
||||||
|
|
||||||
|
// Helper function to continue chaining intermediate results.
|
||||||
|
var result = function(obj, chain) {
|
||||||
|
return chain ? _(obj).chain() : obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A method to easily add functions to the OOP wrapper.
|
||||||
|
var addToWrapper = function(name, func) {
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
unshift.call(args, this._wrapped);
|
||||||
|
return result(func.apply(_, args), this._chain);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all of the Underscore functions to the wrapper object.
|
||||||
|
_.mixin(_);
|
||||||
|
|
||||||
|
// Add all mutator Array functions to the wrapper.
|
||||||
|
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
method.apply(this._wrapped, arguments);
|
||||||
|
return result(this._wrapped, this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add all accessor Array functions to the wrapper.
|
||||||
|
each(['concat', 'join', 'slice'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start chaining a wrapped Underscore object.
|
||||||
|
wrapper.prototype.chain = function() {
|
||||||
|
this._chain = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts the result from a wrapped and chained object.
|
||||||
|
wrapper.prototype.value = function() {
|
||||||
|
return this._wrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
58
node_modules/esprima/test/benchmarks.html
generated
vendored
Normal file
58
node_modules/esprima/test/benchmarks.html
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Benchmarks</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<script src="benchmarks.js"></script>
|
||||||
|
<script src="3rdparty/benchmark.js"></script>
|
||||||
|
<script src="3rdparty/XMLHttpRequest.js"></script>
|
||||||
|
<script>
|
||||||
|
/*jslint browser:true, sloppy:true */
|
||||||
|
/*global setupBenchmarks:true*/
|
||||||
|
window.onload = function () {
|
||||||
|
window.setTimeout(setupBenchmarks, 211);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Benchmarks <small>show the speed</small></h1>
|
||||||
|
|
||||||
|
<p>Time measurement is carried out using <a href="http://benchmarkjs.com" target="_blank">Benchmark.js</a><span id="benchmarkjs-version"></span>.</p>
|
||||||
|
|
||||||
|
<p>Esprima version <span id="version"></span>.</p>
|
||||||
|
|
||||||
|
<p id="status">Please wait...</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<input id="runquick" type="submit" value="Run quick benchmarks" disabled xstyle="visibility: hidden;"/>
|
||||||
|
<input id="runfull" type="submit" value="Run full benchmarks" disabled xstyle="visibility: hidden;"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p id="result"></p>
|
||||||
|
|
||||||
|
<p><strong>Note</strong>: On a modern machine and up-to-date web browsers,
|
||||||
|
running full benchmarks suite takes around 1 minute.<br>
|
||||||
|
For the quick benchmarks, the running time is only about 15 seconds.</p>
|
||||||
|
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
328
node_modules/esprima/test/benchmarks.js
generated
vendored
Normal file
328
node_modules/esprima/test/benchmarks.js
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@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 browser: true node: true */
|
||||||
|
/*global load:true, print:true */
|
||||||
|
var setupBenchmarks,
|
||||||
|
fixture;
|
||||||
|
|
||||||
|
fixture = [
|
||||||
|
'jQuery 1.7.1',
|
||||||
|
'jQuery 1.6.4',
|
||||||
|
'jQuery.Mobile 1.0',
|
||||||
|
'Prototype 1.7.0.0',
|
||||||
|
'Prototype 1.6.1',
|
||||||
|
'Ext Core 3.1.0',
|
||||||
|
'Ext Core 3.0.0',
|
||||||
|
'MooTools 1.4.1',
|
||||||
|
'MooTools 1.3.2',
|
||||||
|
'Backbone 0.5.3',
|
||||||
|
'Underscore 1.2.3'
|
||||||
|
];
|
||||||
|
|
||||||
|
function slug(name) {
|
||||||
|
'use strict';
|
||||||
|
return name.toLowerCase().replace(/\s/g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
function kb(bytes) {
|
||||||
|
'use strict';
|
||||||
|
return (bytes / 1024).toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
// Run all tests in a browser environment.
|
||||||
|
setupBenchmarks = function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function id(i) {
|
||||||
|
return document.getElementById(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(id, str) {
|
||||||
|
var el = document.getElementById(id);
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = str;
|
||||||
|
} else {
|
||||||
|
el.textContent = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableRunButtons() {
|
||||||
|
id('runquick').disabled = false;
|
||||||
|
id('runfull').disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableRunButtons() {
|
||||||
|
id('runquick').disabled = true;
|
||||||
|
id('runfull').disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTable() {
|
||||||
|
var str = '',
|
||||||
|
index,
|
||||||
|
test,
|
||||||
|
name;
|
||||||
|
|
||||||
|
str += '<table>';
|
||||||
|
str += '<thead><tr><th>Source</th><th>Size (KiB)</th>';
|
||||||
|
str += '<th>Time (ms)</th><th>Variance</th></tr></thead>';
|
||||||
|
str += '<tbody>';
|
||||||
|
for (index = 0; index < fixture.length; index += 1) {
|
||||||
|
test = fixture[index];
|
||||||
|
name = slug(test);
|
||||||
|
str += '<tr>';
|
||||||
|
str += '<td>' + test + '</td>';
|
||||||
|
str += '<td id="' + name + '-size"></td>';
|
||||||
|
str += '<td id="' + name + '-time"></td>';
|
||||||
|
str += '<td id="' + name + '-variance"></td>';
|
||||||
|
str += '</tr>';
|
||||||
|
}
|
||||||
|
str += '<tr><td><b>Total</b></td>';
|
||||||
|
str += '<td id="total-size"></td>';
|
||||||
|
str += '<td id="total-time"></td>';
|
||||||
|
str += '<td></td></tr>';
|
||||||
|
str += '</tbody>';
|
||||||
|
str += '</table>';
|
||||||
|
|
||||||
|
id('result').innerHTML = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadTests() {
|
||||||
|
|
||||||
|
var index = 0,
|
||||||
|
totalSize = 0;
|
||||||
|
|
||||||
|
function load(test, callback) {
|
||||||
|
var xhr = new XMLHttpRequest(),
|
||||||
|
src = '3rdparty/' + test + '.js';
|
||||||
|
|
||||||
|
window.data = window.data || {};
|
||||||
|
window.data[test] = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
xhr.timeout = 30000;
|
||||||
|
xhr.open('GET', src, true);
|
||||||
|
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
setText('status', 'Error: time out while loading ' + test);
|
||||||
|
callback.apply();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
var success = false,
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
if (this.readyState === XMLHttpRequest.DONE) {
|
||||||
|
if (this.status === 200) {
|
||||||
|
window.data[test] = this.responseText;
|
||||||
|
size = this.responseText.length;
|
||||||
|
totalSize += size;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
setText(test + '-size', kb(size));
|
||||||
|
} else {
|
||||||
|
setText('status', 'Please wait. Error loading ' + src);
|
||||||
|
setText(test + '-size', 'Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.apply();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(null);
|
||||||
|
} catch (e) {
|
||||||
|
setText('status', 'Please wait. Error loading ' + src);
|
||||||
|
callback.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadNextTest() {
|
||||||
|
var test;
|
||||||
|
|
||||||
|
if (index < fixture.length) {
|
||||||
|
test = fixture[index];
|
||||||
|
index += 1;
|
||||||
|
setText('status', 'Please wait. Loading ' + test +
|
||||||
|
' (' + index + ' of ' + fixture.length + ')');
|
||||||
|
window.setTimeout(function () {
|
||||||
|
load(slug(test), loadNextTest);
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
setText('total-size', kb(totalSize));
|
||||||
|
setText('status', 'Ready.');
|
||||||
|
enableRunButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadNextTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runBenchmarks(suite) {
|
||||||
|
|
||||||
|
var index = 0,
|
||||||
|
totalTime = 0;
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
var i, name;
|
||||||
|
for (i = 0; i < fixture.length; i += 1) {
|
||||||
|
name = slug(fixture[i]);
|
||||||
|
setText(name + '-time', '');
|
||||||
|
setText(name + '-variance', '');
|
||||||
|
}
|
||||||
|
setText('total-time', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
var el, test, source, benchmark;
|
||||||
|
|
||||||
|
if (index >= suite.length) {
|
||||||
|
setText('total-time', (1000 * totalTime).toFixed(1));
|
||||||
|
setText('status', 'Ready.');
|
||||||
|
enableRunButtons();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
test = slug(suite[index]);
|
||||||
|
el = id(test);
|
||||||
|
source = window.data[test];
|
||||||
|
setText(test + '-time', 'Running...');
|
||||||
|
|
||||||
|
// Force the result to be held in this array, thus defeating any
|
||||||
|
// possible "dead core elimination" optimization.
|
||||||
|
window.tree = [];
|
||||||
|
|
||||||
|
benchmark = new window.Benchmark(test, function (o) {
|
||||||
|
var syntax = window.esprima.parse(source);
|
||||||
|
window.tree.push(syntax.body.length);
|
||||||
|
}, {
|
||||||
|
'onComplete': function () {
|
||||||
|
setText(this.name + '-time', (1000 * this.stats.mean).toFixed(1));
|
||||||
|
setText(this.name + '-variance', (1000 * this.stats.variance).toFixed(1));
|
||||||
|
totalTime += this.stats.mean;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.setTimeout(function () {
|
||||||
|
benchmark.run();
|
||||||
|
index += 1;
|
||||||
|
window.setTimeout(run, 211);
|
||||||
|
}, 211);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disableRunButtons();
|
||||||
|
setText('status', 'Please wait. Running benchmarks...');
|
||||||
|
|
||||||
|
reset();
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
|
id('runquick').onclick = function () {
|
||||||
|
runBenchmarks(['jQuery 1.7.1', 'jQuery.Mobile 1.0', 'Backbone 0.5.3']);
|
||||||
|
};
|
||||||
|
|
||||||
|
id('runfull').onclick = function () {
|
||||||
|
runBenchmarks(fixture);
|
||||||
|
};
|
||||||
|
|
||||||
|
setText('benchmarkjs-version', ' version ' + window.Benchmark.version);
|
||||||
|
setText('version', window.esprima.version);
|
||||||
|
|
||||||
|
createTable();
|
||||||
|
disableRunButtons();
|
||||||
|
loadTests();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
|
||||||
|
(function (global) {
|
||||||
|
'use strict';
|
||||||
|
var Benchmark,
|
||||||
|
esprima,
|
||||||
|
dirname,
|
||||||
|
option,
|
||||||
|
fs,
|
||||||
|
readFileSync,
|
||||||
|
log;
|
||||||
|
|
||||||
|
if (typeof require === 'undefined') {
|
||||||
|
dirname = 'test';
|
||||||
|
load(dirname + '/3rdparty/benchmark.js');
|
||||||
|
load(dirname + '/../esprima.js');
|
||||||
|
Benchmark = global.Benchmark;
|
||||||
|
esprima = global.esprima;
|
||||||
|
readFileSync = global.read;
|
||||||
|
log = print;
|
||||||
|
} else {
|
||||||
|
Benchmark = require('./3rdparty/benchmark');
|
||||||
|
esprima = require('../esprima');
|
||||||
|
fs = require('fs');
|
||||||
|
option = process.argv[2];
|
||||||
|
readFileSync = function readFileSync(filename) {
|
||||||
|
return fs.readFileSync(filename, 'utf-8');
|
||||||
|
};
|
||||||
|
dirname = __dirname;
|
||||||
|
log = console.log.bind(console);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTests(tests) {
|
||||||
|
var index,
|
||||||
|
tree = [],
|
||||||
|
totalTime = 0,
|
||||||
|
totalSize = 0;
|
||||||
|
|
||||||
|
tests.reduce(function (suite, filename) {
|
||||||
|
var source = readFileSync(dirname + '/3rdparty/' + slug(filename) + '.js'),
|
||||||
|
size = source.length;
|
||||||
|
totalSize += size;
|
||||||
|
return suite.add(filename, function () {
|
||||||
|
var syntax = esprima.parse(source);
|
||||||
|
tree.push(syntax.body.length);
|
||||||
|
}, {
|
||||||
|
'onComplete': function (event, bench) {
|
||||||
|
log(this.name +
|
||||||
|
' size ' + kb(size) +
|
||||||
|
' time ' + (1000 * this.stats.mean).toFixed(1) +
|
||||||
|
' variance ' + (1000 * this.stats.variance).toFixed(1));
|
||||||
|
totalTime += this.stats.mean;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, new Benchmark.Suite()).on('complete', function () {
|
||||||
|
log('Total size ' + kb(totalSize) +
|
||||||
|
' time ' + (1000 * totalTime).toFixed(1));
|
||||||
|
}).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option === 'quick') {
|
||||||
|
runTests(['jQuery 1.7.1', 'jQuery.Mobile 1.0', 'Backbone 0.5.3']);
|
||||||
|
} else {
|
||||||
|
runTests(fixture);
|
||||||
|
}
|
||||||
|
}(this));
|
||||||
|
}
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
130
node_modules/esprima/test/compare.html
generated
vendored
Normal file
130
node_modules/esprima/test/compare.html
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Speed Comparison</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<script src="compare.js"></script>
|
||||||
|
<script src="3rdparty/benchmark.js"></script>
|
||||||
|
<script src="3rdparty/XMLHttpRequest.js"></script>
|
||||||
|
|
||||||
|
<!-- Mozilla Narcissus -->
|
||||||
|
<script src="3rdparty/jsdefs.js"></script>
|
||||||
|
<script src="3rdparty/jslex.js"></script>
|
||||||
|
<script src="3rdparty/jsparse.js"></script>
|
||||||
|
|
||||||
|
<!-- ZeParser (https://github.com/qfox/ZeParser) -->
|
||||||
|
<script src="3rdparty/Tokenizer.js"></script>
|
||||||
|
<script src="3rdparty/ZeParser.js"></script>
|
||||||
|
|
||||||
|
<!-- parse-js, part of UglifyJS -->
|
||||||
|
<script>
|
||||||
|
/*global exports: true, window: true*/
|
||||||
|
exports = window.parseJS = {};
|
||||||
|
</script>
|
||||||
|
<script src="3rdparty/parse-js.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/*global runBenchmarks: true*/
|
||||||
|
window.onload = function () {
|
||||||
|
'use strict';
|
||||||
|
window.setTimeout(runBenchmarks, 211);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Compare <small>with other parsers</small></h1>
|
||||||
|
|
||||||
|
<p>Time measurement is carried out using <a href="http://benchmarkjs.com" target="_blank">Benchmark.js</a><span id="benchmarkjs-version"></span>.</p>
|
||||||
|
|
||||||
|
<p>Esprima version <span id="version"></span>.</p>
|
||||||
|
|
||||||
|
<p><span id="status">Please wait...</span>
|
||||||
|
<input id="run" type="submit" value="Run speed comparison" disabled /></p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Source</th>
|
||||||
|
<th>Size (KiB)</th>
|
||||||
|
<th>Esprima</th>
|
||||||
|
<th>parse-js</th>
|
||||||
|
<th>ZeParser</th>
|
||||||
|
<th>Narcissus</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>jQuery 1.7.1</td>
|
||||||
|
<td id="jquery-1.7.1-size"></td>
|
||||||
|
<td id="esprima-jquery-1.7.1"></td>
|
||||||
|
<td id="parsejs-jquery-1.7.1"></td>
|
||||||
|
<td id="zeparser-jquery-1.7.1"></td>
|
||||||
|
<td id="narcissus-jquery-1.7.1"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Prototype 1.7.0.0</td>
|
||||||
|
<td id="prototype-1.7.0.0-size"></td>
|
||||||
|
<td id="esprima-prototype-1.7.0.0"></td>
|
||||||
|
<td id="parsejs-prototype-1.7.0.0"></td>
|
||||||
|
<td id="zeparser-prototype-1.7.0.0"></td>
|
||||||
|
<td id="narcissus-prototype-1.7.0.0"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MooTools 1.4.1</td>
|
||||||
|
<td id="mootools-1.4.1-size"></td>
|
||||||
|
<td id="esprima-mootools-1.4.1"></td>
|
||||||
|
<td id="parsejs-mootools-1.4.1"></td>
|
||||||
|
<td id="zeparser-mootools-1.4.1"></td>
|
||||||
|
<td id="narcissus-mootools-1.4.1"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ext Core 3.1.0</td>
|
||||||
|
<td id="ext-core-3.1.0-size"></td>
|
||||||
|
<td id="esprima-ext-core-3.1.0"></td>
|
||||||
|
<td id="parsejs-ext-core-3.1.0"></td>
|
||||||
|
<td id="zeparser-ext-core-3.1.0"></td>
|
||||||
|
<td id="narcissus-ext-core-3.1.0"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Total</td>
|
||||||
|
<td id="total-size"></td>
|
||||||
|
<td id="esprima-time"></td>
|
||||||
|
<td id="parsejs-time"></td>
|
||||||
|
<td id="zeparser-time"></td>
|
||||||
|
<td id="narcissus-time"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p><strong>Warning:</strong> Since each parser has a different format for the syntax tree, the speed is not fully comparable (the cost of constructing different result is not taken into account). These tests exist only to ensure that Esprima parser is not ridiculously slow, e.g. one magnitude slower compare to other parsers.</p>
|
||||||
|
|
||||||
|
<p><strong>parse-js</strong> is the parser used in <a href="https://github.com/mishoo/UglifyJS">UglifyJS</a>. It's a JavaScript port of the Common LISP version. This test uses <code>parse-js</code> from UglifyJS version 1.2.5 (Jan 13 2011).</p>
|
||||||
|
|
||||||
|
<p><strong>ZeParser</strong> is from <a href="https://github.com/qfox/ZeParser">github.com/qfox/ZeParser</a> revision 51e52908 (dated Dec 24 2011). Beside the syntax tree, ZeParser also provides location info for the syntax nodes, as well as the list of all tokens.</p>
|
||||||
|
|
||||||
|
<p><strong>Narcissus</strong> is Mozilla's JavaScript engine implemented in JavaScript. This test uses the parser from Narcissus, taken from its
|
||||||
|
<a href="https://github.com/mozilla/narcissus">code repository</a> revision b5caa7df (dated Oct 26 2011). Narcissus supports many extensions (generators, comprehension, destructuring, etc) and therefore it takes longer to parse JavaScript code. Narcissus parser output also contains the location info for the syntax node. <strong>Note</strong>: Narcissus will not work if <code>Object.create</code> and <code>Object.defineProperty</code> are not available.</p>
|
||||||
|
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
258
node_modules/esprima/test/compare.js
generated
vendored
Normal file
258
node_modules/esprima/test/compare.js
generated
vendored
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
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 browser: true */
|
||||||
|
|
||||||
|
function runBenchmarks() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var index = 0,
|
||||||
|
totalSize = 0,
|
||||||
|
totalTime = {},
|
||||||
|
fixture;
|
||||||
|
|
||||||
|
fixture = [
|
||||||
|
'esprima jquery-1.7.1',
|
||||||
|
'parsejs jquery-1.7.1',
|
||||||
|
'zeparser jquery-1.7.1',
|
||||||
|
'narcissus jquery-1.7.1',
|
||||||
|
|
||||||
|
'esprima prototype-1.7.0.0',
|
||||||
|
'parsejs prototype-1.7.0.0',
|
||||||
|
'zeparser prototype-1.7.0.0',
|
||||||
|
'narcissus prototype-1.7.0.0',
|
||||||
|
|
||||||
|
'esprima mootools-1.4.1',
|
||||||
|
'parsejs mootools-1.4.1',
|
||||||
|
'zeparser mootools-1.4.1',
|
||||||
|
'narcissus mootools-1.4.1',
|
||||||
|
|
||||||
|
'esprima ext-core-3.1.0',
|
||||||
|
'parsejs ext-core-3.1.0',
|
||||||
|
'zeparser ext-core-3.1.0',
|
||||||
|
'narcissus ext-core-3.1.0'
|
||||||
|
];
|
||||||
|
|
||||||
|
function id(i) {
|
||||||
|
return document.getElementById(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function kb(bytes) {
|
||||||
|
return (bytes / 1024).toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(id, str) {
|
||||||
|
var el = document.getElementById(id);
|
||||||
|
if (typeof el.innerText === 'string') {
|
||||||
|
el.innerText = str;
|
||||||
|
} else {
|
||||||
|
el.textContent = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ready() {
|
||||||
|
setText('status', 'Ready.');
|
||||||
|
id('run').disabled = false;
|
||||||
|
id('run').style.visibility = 'visible';
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(tst, callback) {
|
||||||
|
var xhr = new XMLHttpRequest(),
|
||||||
|
src = '3rdparty/' + tst + '.js';
|
||||||
|
|
||||||
|
// Already available? Don't reload from server.
|
||||||
|
if (window.data && window.data.hasOwnProperty(tst)) {
|
||||||
|
callback.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
xhr.timeout = 30000;
|
||||||
|
xhr.open('GET', src, true);
|
||||||
|
setText('status', 'Please wait. Loading ' + src);
|
||||||
|
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
setText('status', 'Please wait. Error: time out while loading ' + src + ' ');
|
||||||
|
callback.apply();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
var success = false,
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
if (this.readyState === XMLHttpRequest.DONE) {
|
||||||
|
if (this.status === 200) {
|
||||||
|
window.data = window.data || {};
|
||||||
|
window.data[tst] = this.responseText;
|
||||||
|
size = this.responseText.length;
|
||||||
|
totalSize += size;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
setText(tst + '-size', kb(size));
|
||||||
|
} else {
|
||||||
|
setText('status', 'Please wait. Error loading ' + src);
|
||||||
|
setText(tst + '-size', 'Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.apply();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(null);
|
||||||
|
} catch (e) {
|
||||||
|
setText('status', 'Please wait. Error loading ' + src);
|
||||||
|
callback.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadTests() {
|
||||||
|
var sources = fixture.slice();
|
||||||
|
|
||||||
|
function loadNextTest() {
|
||||||
|
var tst;
|
||||||
|
|
||||||
|
if (sources.length > 0) {
|
||||||
|
tst = sources[0].split(' ');
|
||||||
|
tst = tst[1];
|
||||||
|
sources.splice(0, 1);
|
||||||
|
window.setTimeout(function () {
|
||||||
|
load(tst, loadNextTest);
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
setText('total-size', kb(totalSize));
|
||||||
|
ready();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id('run').style.visibility = 'hidden';
|
||||||
|
loadNextTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runBenchmark() {
|
||||||
|
var test, source, parser, fn, benchmark;
|
||||||
|
|
||||||
|
if (index >= fixture.length) {
|
||||||
|
setText('total-size', kb(totalSize));
|
||||||
|
setText('esprima-time', (1000 * totalTime.esprima).toFixed(1) + ' ms');
|
||||||
|
setText('parsejs-time', (1000 * totalTime.parsejs).toFixed(1) + ' ms');
|
||||||
|
setText('zeparser-time', (1000 * totalTime.zeparser).toFixed(1) + ' ms');
|
||||||
|
if (totalTime.narcissus > 0) {
|
||||||
|
setText('narcissus-time', (1000 * totalTime.narcissus).toFixed(1) + ' ms');
|
||||||
|
}
|
||||||
|
ready();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
test = fixture[index].split(' ');
|
||||||
|
parser = test[0];
|
||||||
|
test = test[1];
|
||||||
|
|
||||||
|
source = window.data[test];
|
||||||
|
setText(parser + '-' + test, 'Running...');
|
||||||
|
|
||||||
|
// Force the result to be held in this array, thus defeating any
|
||||||
|
// possible "dead core elimination" optimization.
|
||||||
|
window.tree = [];
|
||||||
|
|
||||||
|
switch (parser) {
|
||||||
|
case 'esprima':
|
||||||
|
fn = function () {
|
||||||
|
var syntax = window.esprima.parse(source);
|
||||||
|
window.tree.push(syntax.body.length);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'narcissus':
|
||||||
|
fn = function () {
|
||||||
|
var syntax = window.Narcissus.parser.parse(source);
|
||||||
|
window.tree.push(syntax.children.length);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'parsejs':
|
||||||
|
fn = function () {
|
||||||
|
var syntax = window.parseJS.parse(source);
|
||||||
|
window.tree.push(syntax.length);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'zeparser':
|
||||||
|
fn = function () {
|
||||||
|
var syntax = window.ZeParser.parse(source, false);
|
||||||
|
window.tree.push(syntax.length);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw 'Unknown parser type ' + parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmark = new window.Benchmark(test, fn, {
|
||||||
|
'onComplete': function () {
|
||||||
|
setText(parser + '-' + this.name, (1000 * this.stats.mean).toFixed(1) + ' ms');
|
||||||
|
totalSize += source.length;
|
||||||
|
totalTime[parser] += this.stats.mean;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.setTimeout(function () {
|
||||||
|
benchmark.run();
|
||||||
|
index += 1;
|
||||||
|
window.setTimeout(runBenchmark, 211);
|
||||||
|
}, 211);
|
||||||
|
}
|
||||||
|
|
||||||
|
id('run').onclick = function () {
|
||||||
|
|
||||||
|
var test;
|
||||||
|
|
||||||
|
for (index = 0; index < fixture.length; index += 1) {
|
||||||
|
test = fixture[index].split(' ').join('-');
|
||||||
|
setText(test, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
setText('status', 'Please wait. Running benchmarks...');
|
||||||
|
id('run').style.visibility = 'hidden';
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
totalTime = {
|
||||||
|
'esprima': 0,
|
||||||
|
'narcissus': 0,
|
||||||
|
'parsejs': 0,
|
||||||
|
'zeparser': 0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (test in totalTime) {
|
||||||
|
if (totalTime.hasOwnProperty(test)) {
|
||||||
|
setText(test + '-time', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runBenchmark();
|
||||||
|
};
|
||||||
|
|
||||||
|
setText('benchmarkjs-version', ' version ' + window.Benchmark.version);
|
||||||
|
setText('version', window.esprima.version);
|
||||||
|
|
||||||
|
loadTests();
|
||||||
|
}
|
||||||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
40
node_modules/esprima/test/compat.html
generated
vendored
Normal file
40
node_modules/esprima/test/compat.html
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Compatibility Tests</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<script id="reflect" src="reflect.js"></script>
|
||||||
|
<script src="compat.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Compatibility <small>keeps everyone happy</small></h1>
|
||||||
|
<p>Esprima version <span id="version"></span>.</p>
|
||||||
|
<p>The following tests are to ensure that the syntax tree is compatible to
|
||||||
|
that produced by Mozilla SpiderMonkey
|
||||||
|
<a href="https://developer.mozilla.org/en/SpiderMonkey/Parser_API">Parser reflection</a>.</p>
|
||||||
|
<p id="status">Please wait...</p>
|
||||||
|
<div id="report"></div>
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
/*jslint browser:true*/
|
||||||
|
window.onload = window.runTests;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
239
node_modules/esprima/test/compat.js
generated
vendored
Normal file
239
node_modules/esprima/test/compat.js
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
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) {
|
||||||
|
setText(document.getElementById('status'), total + ' tests. ' +
|
||||||
|
'Failures: ' + failures + '. ' + tick + ' ms');
|
||||||
|
} else {
|
||||||
|
setText(document.getElementById('status'), total + ' tests. ' +
|
||||||
|
'No failure. ' + tick + ' ms');
|
||||||
|
}
|
||||||
|
}, 513);
|
||||||
|
};
|
||||||
|
} 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 : */
|
36
node_modules/esprima/test/index.html
generated
vendored
Normal file
36
node_modules/esprima/test/index.html
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Esprima: Unit Tests</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../assets/style.css"/>
|
||||||
|
<script src="../esprima.js"></script>
|
||||||
|
<script src="../assets/json2.js"></script>
|
||||||
|
<script src="test.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="topbar">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="../index.html">← Home</a></li>
|
||||||
|
<li><a href="http://github.com/ariya/esprima">Code</a></li>
|
||||||
|
<li><a href="http://wiki.esprima.org">Documentation</a></li>
|
||||||
|
<li><a href="http://issues.esprima.org">Issues</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Unit Tests <small>ensures the correct implementation</small></h1>
|
||||||
|
<p>Esprima version <span id="version"></span>.</p>
|
||||||
|
<p id="status">Please wait...</p>
|
||||||
|
<div id="report"></div>
|
||||||
|
<div class="footer"><strong>Esprima</strong> is created by
|
||||||
|
<a href="http://ariya.ofilabs.com/about" target="_blank">Ariya Hidayat</a>. Follow <a href="http://twitter.com/ariyahidayat">@ariyahidayat</a> on Twitter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
/*jslint browser: true */
|
||||||
|
window.onload = window.runTests;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
403
node_modules/esprima/test/reflect.js
generated
vendored
Normal file
403
node_modules/esprima/test/reflect.js
generated
vendored
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
// 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,
|
||||||
|
body: body
|
||||||
|
}) }
|
||||||
|
function genFunDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration",
|
||||||
|
id: id,
|
||||||
|
params: params,
|
||||||
|
body: body
|
||||||
|
}) }
|
||||||
|
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) { return Pattern({ type: "CatchClause", param: id, guard: guard, body: body }) }
|
||||||
|
function tryStmt(body, catches, fin) { return Pattern({ type: "TryStatement", block: body, 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,
|
||||||
|
body: body
|
||||||
|
}) }
|
||||||
|
function genFunExpr(id, args, body) { return Pattern({ type: "FunctionExpression",
|
||||||
|
id: id,
|
||||||
|
params: args,
|
||||||
|
body: body
|
||||||
|
}) }
|
||||||
|
|
||||||
|
function unExpr(op, arg) { return Pattern({ type: "UnaryExpression", operator: op, argument: arg }) }
|
||||||
|
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));
|
66
node_modules/esprima/test/run.js
generated
vendored
Normal file
66
node_modules/esprima/test/run.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
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 = [
|
||||||
|
'test',
|
||||||
|
'compat'
|
||||||
|
];
|
||||||
|
|
||||||
|
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();
|
||||||
|
}());
|
19018
node_modules/esprima/test/test.js
generated
vendored
Normal file
19018
node_modules/esprima/test/test.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
146
node_modules/pegjs/CHANGELOG
generated
vendored
146
node_modules/pegjs/CHANGELOG
generated
vendored
@ -1,146 +0,0 @@
|
|||||||
0.6.2 (2011-08-20)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* Reset parser position when action returns |null|.
|
|
||||||
* Fixed typo in JavaScript example grammar.
|
|
||||||
|
|
||||||
0.6.1 (2011-04-14)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* Use --ascii option when generating a minified version.
|
|
||||||
|
|
||||||
0.6.0 (2011-04-14)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Big Changes:
|
|
||||||
|
|
||||||
* Rewrote the command-line mode to be based on Node.js instead of Rhino -- no
|
|
||||||
more Java dependency. This also means that PEG.js is available as a Node.js
|
|
||||||
package and can be required as a module.
|
|
||||||
* Version for the browser is built separately from the command-ine one in two
|
|
||||||
flavors (normal and minified).
|
|
||||||
* Parser variable name is no longer required argument of bin/pegjs -- it is
|
|
||||||
"module.exports" by default and can be set using the -e/--export-var option.
|
|
||||||
This makes parsers generated by /bin/pegjs Node.js modules by default.
|
|
||||||
* Added ability to start parsing from any grammar rule.
|
|
||||||
* Added several compiler optimizations -- 0.6 is ~12% faster than 0.5.1 in the
|
|
||||||
benchmark on V8.
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* Split the source code into multiple files combined together using a build
|
|
||||||
system.
|
|
||||||
* Jake is now used instead of Rake for build scripts -- no more Ruby dependency.
|
|
||||||
* Test suite can be run from the command-line.
|
|
||||||
* Benchmark suite can be run from the command-line.
|
|
||||||
* Benchmark browser runner improvements (users can specify number of runs,
|
|
||||||
benchmarks are run using |setTimeout|, table is centered and fixed-width).
|
|
||||||
* Added PEG.js version to "Generated by..." line in generated parsers.
|
|
||||||
* Added PEG.js version information and homepage header to peg.js.
|
|
||||||
* Generated code improvements and fixes.
|
|
||||||
* Internal code improvements and fixes.
|
|
||||||
* Rewrote README.md.
|
|
||||||
|
|
||||||
0.5.1 (2010-11-28)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* Fixed a problem where "SyntaxError: Invalid range in character class." error
|
|
||||||
appeared when using command-line version on Widnows (GH-13).
|
|
||||||
* Fixed wrong version reported by "bin/pegjs --version".
|
|
||||||
* Removed two unused variables in the code.
|
|
||||||
* Fixed incorrect variable name on two places.
|
|
||||||
|
|
||||||
0.5 (2010-06-10)
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Big Changes:
|
|
||||||
|
|
||||||
* Syntax change: Use labeled expressions and variables instead of $1, $2, etc.
|
|
||||||
* Syntax change: Replaced ":" after a rule name with "=".
|
|
||||||
* Syntax change: Allow trailing semicolon (";") for rules
|
|
||||||
* Semantic change: Start rule of the grammar is now implicitly its first rule.
|
|
||||||
* Implemented semantic predicates.
|
|
||||||
* Implemented initializers.
|
|
||||||
* Removed ability to change the start rule when generating the parser.
|
|
||||||
* Added several compiler optimizations -- 0.5 is ~11% faster than 0.4 in the
|
|
||||||
benchmark on V8.
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* PEG.buildParser now accepts grammars only in string format.
|
|
||||||
* Added "Generated by ..." message to the generated parsers.
|
|
||||||
* Formatted all grammars more consistently and transparently.
|
|
||||||
* Added notes about ECMA-262, 5th ed. compatibility to the JSON example grammar.
|
|
||||||
* Guarded against redefinition of |undefined|.
|
|
||||||
* Made bin/pegjs work when called via a symlink (issue #1).
|
|
||||||
* Fixed bug causing incorrect error messages (issue #2).
|
|
||||||
* Fixed error message for invalid character range.
|
|
||||||
* Fixed string literal parsing in the JavaScript grammar.
|
|
||||||
* Generated code improvements and fixes.
|
|
||||||
* Internal code improvements and fixes.
|
|
||||||
* Improved README.md.
|
|
||||||
|
|
||||||
0.4 (2010-04-17)
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Big Changes:
|
|
||||||
|
|
||||||
* Improved IE compatibility -- IE6+ is now fully supported.
|
|
||||||
* Generated parsers are now standalone (no runtime is required).
|
|
||||||
* Added example grammars for JavaScript, CSS and JSON.
|
|
||||||
* Added a benchmark suite.
|
|
||||||
* Implemented negative character classes (e.g. [^a-z]).
|
|
||||||
* Project moved from BitBucket to GitHub.
|
|
||||||
|
|
||||||
Small Changes:
|
|
||||||
|
|
||||||
* Code generated for the character classes is now regexp-based (= simpler and
|
|
||||||
more scalable).
|
|
||||||
* Added \uFEFF (BOM) to the definition of whitespace in the metagrammar.
|
|
||||||
* When building a parser, left-recursive rules (both direct and indirect) are
|
|
||||||
reported as errors.
|
|
||||||
* When building a parser, missing rules are reported as errors.
|
|
||||||
* Expected items in the error messages do not contain duplicates and they are
|
|
||||||
sorted.
|
|
||||||
* Fixed several bugs in the example arithmetics grammar.
|
|
||||||
* Converted README to GitHub Flavored Markdown and improved it.
|
|
||||||
* Added CHANGELOG.
|
|
||||||
* Internal code improvements.
|
|
||||||
|
|
||||||
0.3 (2010-03-14)
|
|
||||||
----------------
|
|
||||||
|
|
||||||
* Wrote README.
|
|
||||||
* Bootstrapped the grammar parser.
|
|
||||||
* Metagrammar recognizes JavaScript-like comments.
|
|
||||||
* Changed standard grammar extension from .peg to .pegjs (it is more specific).
|
|
||||||
* Simplified the example arithmetics grammar + added comment.
|
|
||||||
* Fixed a bug with reporting of invalid ranges such as [b-a] in the metagrammar.
|
|
||||||
* Fixed --start vs. --start-rule inconsistency between help and actual option
|
|
||||||
processing code.
|
|
||||||
* Avoided ugliness in QUnit output.
|
|
||||||
* Fixed typo in help: "parserVar" -> "parser_var".
|
|
||||||
* Internal code improvements.
|
|
||||||
|
|
||||||
0.2.1 (2010-03-08)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
* Added "pegjs-" prefix to the name of the minified runtime file.
|
|
||||||
|
|
||||||
0.2 (2010-03-08)
|
|
||||||
----------------
|
|
||||||
|
|
||||||
* Added Rakefile that builds minified runtime using Google Closure Compiler API.
|
|
||||||
* Removed trailing commas in object initializers (Google Closure does not like
|
|
||||||
them).
|
|
||||||
|
|
||||||
0.1 (2010-03-08)
|
|
||||||
----------------
|
|
||||||
|
|
||||||
* Initial release.
|
|
22
node_modules/pegjs/LICENSE
generated
vendored
22
node_modules/pegjs/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
Copyright (c) 2010-2011 David Majda
|
|
||||||
|
|
||||||
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.
|
|
226
node_modules/pegjs/README.md
generated
vendored
226
node_modules/pegjs/README.md
generated
vendored
@ -1,226 +0,0 @@
|
|||||||
PEG.js
|
|
||||||
======
|
|
||||||
|
|
||||||
PEG.js is a simple parser generator for JavaScript that produces fast parsers with excellent error reporting. You can use it to process complex data or computer languages and build transformers, interpreters, compilers and other tools easily.
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
* Simple and expressive grammar syntax
|
|
||||||
* Integrates both lexical and syntactical analysis
|
|
||||||
* Parsers have excellent error reporting out of the box
|
|
||||||
* Based on [parsing expression grammar](http://en.wikipedia.org/wiki/Parsing_expression_grammar) formalism — more powerful than traditional LL(*k*) and LR(*k*) parsers
|
|
||||||
* Usable [from your browser](http://pegjs.majda.cz/online), from the command line, or via JavaScript API
|
|
||||||
|
|
||||||
Getting Started
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Online version](http://pegjs.majda.cz/online) is the easiest way to generate a parser. Just enter your grammar, try parsing few inputs, and download generated parser code.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
### Command Line / Server-side
|
|
||||||
|
|
||||||
To use command-line version, install [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) first. You can then install PEG.js:
|
|
||||||
|
|
||||||
$ npm install pegjs
|
|
||||||
|
|
||||||
Once installed, you can use the `pegjs` command to generate your parser from a grammar and use the JavaScript API from Node.js.
|
|
||||||
|
|
||||||
### Browser
|
|
||||||
|
|
||||||
[Download](http://pegjs.majda.cz/#download) the PEG.js library (regular or minified version) and include it in your web page or application using the `<script>` tag.
|
|
||||||
|
|
||||||
Generating a Parser
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
PEG.js generates parser from a grammar that describes expected input and can specify what the parser returns (using semantic actions on matched parts of the input). Generated parser itself is a JavaScript object with a simple API.
|
|
||||||
|
|
||||||
### Command Line
|
|
||||||
|
|
||||||
To generate a parser from your grammar, use the `pegjs` command:
|
|
||||||
|
|
||||||
$ pegjs arithmetics.pegjs
|
|
||||||
|
|
||||||
This writes parser source code into a file with the same name as the grammar file but with “.js” extension. You can also specify the output file explicitly:
|
|
||||||
|
|
||||||
$ pegjs arithmetics.pegjs arithmetics-parser.js
|
|
||||||
|
|
||||||
If you omit both input and ouptut file, standard input and output are used.
|
|
||||||
|
|
||||||
By default, the parser object is assigned to `module.exports`, which makes the output a Node.js module. You can assign it to another variable by passing a variable name using the `-e`/`--export-var` option. This may be helpful if you want to use the parser in browser environment.
|
|
||||||
|
|
||||||
### JavaScript API
|
|
||||||
|
|
||||||
In Node.js, require the PEG.js parser generator module:
|
|
||||||
|
|
||||||
var PEG = require("pegjs");
|
|
||||||
|
|
||||||
In browser, include the PEG.js library in your web page or application using the `<script>` tag. The API will be available through the `PEG` global object.
|
|
||||||
|
|
||||||
To generate a parser, call the `PEG.buildParser` method and pass your grammar as a parameter:
|
|
||||||
|
|
||||||
var parser = PEG.buildParser("start = ('a' / 'b')+");
|
|
||||||
|
|
||||||
The method will return generated parser object or throw an exception if the grammar is invalid. The exception will contain `message` property with more details about the error.
|
|
||||||
|
|
||||||
To get parser’s source code, call the `toSource` method on the parser.
|
|
||||||
|
|
||||||
Using the Parser
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Using the generated parser is simple — just call its `parse` method and pass an input string as a parameter. The method will return a parse result (the exact value depends on the grammar used to build the parser) or throw an exception if the input is invalid. The exception will contain `line`, `column` and `message` properties with more details about the error.
|
|
||||||
|
|
||||||
parser.parse("abba"); // returns ["a", "b", "b", "a"]
|
|
||||||
|
|
||||||
parser.parse("abcd"); // throws an exception
|
|
||||||
|
|
||||||
You can also start parsing from a specific rule in the grammar. Just pass the rule name to the `parse` method as a second parameter.
|
|
||||||
|
|
||||||
Grammar Syntax and Semantics
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
The grammar syntax is similar to JavaScript in that it is not line-oriented and ignores whitespace between tokens. You can also use JavaScript-style comments (`// ...` and `/* ... */`).
|
|
||||||
|
|
||||||
Let's look at example grammar that recognizes simple arithmetic expressions like `2*(3+4)`. A parser generated from this grammar computes their values.
|
|
||||||
|
|
||||||
start
|
|
||||||
= additive
|
|
||||||
|
|
||||||
additive
|
|
||||||
= left:multiplicative "+" right:additive { return left + right; }
|
|
||||||
/ multiplicative
|
|
||||||
|
|
||||||
multiplicative
|
|
||||||
= left:primary "*" right:multiplicative { return left * right; }
|
|
||||||
/ primary
|
|
||||||
|
|
||||||
primary
|
|
||||||
= integer
|
|
||||||
/ "(" additive:additive ")" { return additive; }
|
|
||||||
|
|
||||||
integer "integer"
|
|
||||||
= digits:[0-9]+ { return parseInt(digits.join(""), 10); }
|
|
||||||
|
|
||||||
On the top level, the grammar consists of *rules* (in our example, there are five of them). Each rule has a *name* (e.g. `integer`) that identifies the rule, and a *parsing expression* (e.g. `digits:[0-9]+ { return parseInt(digits.join(""), 10); }`) that defines a pattern to match against the input text and possibly contains some JavaScript code that determines what happens when the pattern matches successfully. A rule can also contain *human-readable name* that is used in error messages (in our example, only the `integer` rule has a human-readable name). The parsing starts at the first rule, which is also called the *start rule*.
|
|
||||||
|
|
||||||
A rule name must be a JavaScript identifier. It is followed by an equality sign (“=”) and a parsing expression. If the rule has a human-readable name, it is written as a JavaScript string between the name and separating equality sign. Rules need to be separated only by whitespace (their beginning is easily recognizable), but a semicolon (“;”) after the parsing expression is allowed.
|
|
||||||
|
|
||||||
Rules can be preceded by an *initializer* — a piece of JavaScript code in curly braces (“{” and “}”). This code is executed before the generated parser starts parsing. All variables and functions defined in the initializer are accessible in rule actions and semantic predicates. Curly braces in the initializer code must be balanced.
|
|
||||||
|
|
||||||
The parsing expressions of the rules are used to match the input text to the grammar. There are various types of expressions — matching characters or character classes, indicating optional parts and repetition, etc. Expressions can also contain references to other rules. See detailed description below.
|
|
||||||
|
|
||||||
If an expression successfully matches a part of the text when running the generated parser, it produces a *match result*, which is a JavaScript value. For example:
|
|
||||||
|
|
||||||
* An expression matching a literal string produces a JavaScript string containing matched part of the input.
|
|
||||||
* An expression matching repeated occurrence of some subexpression produces a JavaScript array with all the matches.
|
|
||||||
|
|
||||||
The match results propagate through the rules when the rule names are used in expressions, up to the start rule. The generated parser returns start rule's match result when parsing is successful.
|
|
||||||
|
|
||||||
One special case of parser expression is a *parser action* — a piece of JavaScript code inside curly braces (“{” and “}”) that takes match results of some of the the preceding expressions and returns a JavaScript value. This value is considered match result of the preceding expression (in other words, the parser action is a match result transformer).
|
|
||||||
|
|
||||||
In our arithmetics example, there are many parser actions. Consider the action in expression `digits:[0-9]+ { return parseInt(digits.join(""), 10); }`. It takes the match result of the expression [0-9]+, which is an array of strings containing digits, as its parameter. It joins the digits together to form a number and converts it to a JavaScript `number` object.
|
|
||||||
|
|
||||||
### Parsing Expression Types
|
|
||||||
|
|
||||||
There are several types of parsing expressions, some of them containing subexpressions and thus forming a recursive structure:
|
|
||||||
|
|
||||||
#### "*literal*"<br>'*literal*'
|
|
||||||
|
|
||||||
Match exact literal string and return it. The string syntax is the same as in JavaScript.
|
|
||||||
|
|
||||||
#### .
|
|
||||||
|
|
||||||
Match exactly one character and return it as a string.
|
|
||||||
|
|
||||||
#### [*characters*]
|
|
||||||
|
|
||||||
Match one character from a set and return it as a string. The characters in the list can be escaped in exactly the same way as in JavaScript string. The list of characters can also contain ranges (e.g. `[a-z]` means “all lowercase letters”). Preceding the characters with `^` inverts the matched set (e.g. `[^a-z]` means “all character but lowercase letters”).
|
|
||||||
|
|
||||||
#### *rule*
|
|
||||||
|
|
||||||
Match a parsing expression of a rule recursively and return its match result.
|
|
||||||
|
|
||||||
#### ( *expression* )
|
|
||||||
|
|
||||||
Match a subexpression and return its match result.
|
|
||||||
|
|
||||||
#### *expression* \*
|
|
||||||
|
|
||||||
Match zero or more repetitions of the expression and return their match results in an array. The matching is greedy, i.e. the parser tries to match the expression as many times as possible.
|
|
||||||
|
|
||||||
#### *expression* +
|
|
||||||
|
|
||||||
Match one or more repetitions of the expression and return their match results in an array. The matching is greedy, i.e. the parser tries to match the expression as many times as possible.
|
|
||||||
|
|
||||||
#### *expression* ?
|
|
||||||
|
|
||||||
Try to match the expression. If the match succeeds, return its match result, otherwise return an empty string.
|
|
||||||
|
|
||||||
#### & *expression*
|
|
||||||
|
|
||||||
Try to match the expression. If the match succeeds, just return an empty string and do not advance the parser position, otherwise consider the match failed.
|
|
||||||
|
|
||||||
#### ! *expression*
|
|
||||||
|
|
||||||
Try to match the expression and. If the match does not succeed, just return an empty string and do not advance the parser position, otherwise consider the match failed.
|
|
||||||
|
|
||||||
#### & { *predicate* }
|
|
||||||
|
|
||||||
The predicate is a piece of JavaScript code that is executed as if it was inside a function. It should return some JavaScript value using the `return` statement. If the returned value evaluates to `true` in boolean context, just return an empty string and do not advance the parser position; otherwise consider the match failed.
|
|
||||||
|
|
||||||
The code inside the predicate has access to all variables and functions defined in the initializer at the beginning of the grammar. Curly braces in the predicate code must be balanced.
|
|
||||||
|
|
||||||
#### ! { *predicate* }
|
|
||||||
|
|
||||||
The predicate is a piece of JavaScript code that is executed as if it was inside a function. It should return some JavaScript value using the `return` statement. If the returned value evaluates to `false` in boolean context, just return an empty string and do not advance the parser position; otherwise consider the match failed.
|
|
||||||
|
|
||||||
The code inside the predicate has access to all variables and functions defined in the initializer at the beginning of the grammar. Curly braces in the predicate code must be balanced.
|
|
||||||
|
|
||||||
#### *label* : *expression*
|
|
||||||
|
|
||||||
Match the expression and remember its match result under given lablel. The label must be a JavaScript identifier.
|
|
||||||
|
|
||||||
Labeled expressions are useful together with actions, where saved match results can be accessed by action's JavaScript code.
|
|
||||||
|
|
||||||
#### *expression<sub>1</sub>* *expression<sub>2</sub>* ... *expression<sub>n</sub>*
|
|
||||||
|
|
||||||
Match a sequence of expressions and return their match results in an array.
|
|
||||||
|
|
||||||
#### *expression* { *action* }
|
|
||||||
|
|
||||||
Match the expression. If the match is successful, run the action, otherwise consider the match failed.
|
|
||||||
|
|
||||||
The action is a piece of JavaScript code that is executed as if it was inside a function. It gets the match results of labeled expressions in preceding expression as its arguments. The action should return some JavaScript value using the `return` statement. This value is considered match result of the preceding expression. The action can return `null` to indicate a match failure.
|
|
||||||
|
|
||||||
The code inside the action has access to all variables and functions defined in the initializer at the beginning of the grammar. Curly braces in the action code must be balanced.
|
|
||||||
|
|
||||||
#### *expression<sub>1</sub>* / *expression<sub>2</sub>* / ... / *expression<sub>n</sub>*
|
|
||||||
|
|
||||||
Try to match the first expression, if it does not succeed, try the second one, etc. Return the match result of the first successfully matched expression. If no expression matches, consider the match failed.
|
|
||||||
|
|
||||||
Compatibility
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Both the parser generator and generated parsers should run well in the following environments:
|
|
||||||
|
|
||||||
* Node.js 0.4.4+
|
|
||||||
* IE 6+
|
|
||||||
* Firefox
|
|
||||||
* Chrome
|
|
||||||
* Safari
|
|
||||||
* Opera
|
|
||||||
|
|
||||||
Development
|
|
||||||
-----------
|
|
||||||
|
|
||||||
* [Project website](https://pegjs.majda.cz/)
|
|
||||||
* [Source code](https://github.com/dmajda/pegjs)
|
|
||||||
* [Issue tracker](https://github.com/dmajda/pegjs/issues)
|
|
||||||
* [Google Group](http://groups.google.com/group/pegjs)
|
|
||||||
* [Twitter](http://twitter.com/peg_js)
|
|
||||||
|
|
||||||
PEG.js is developed by [David Majda](http://majda.cz/) ([@dmajda](http://twitter.com/dmajda)). You are welcome to contribute code. Unless your contribution is really trivial you should get in touch with me first — this can prevent wasted effort on both sides. You can send code both as patch or GitHub pull request.
|
|
||||||
|
|
||||||
Note that PEG.js is still very much work in progress. There are no compatibility guarantees until version 1.0.
|
|
1
node_modules/pegjs/VERSION
generated
vendored
1
node_modules/pegjs/VERSION
generated
vendored
@ -1 +0,0 @@
|
|||||||
0.6.2
|
|
142
node_modules/pegjs/bin/pegjs
generated
vendored
142
node_modules/pegjs/bin/pegjs
generated
vendored
@ -1,142 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var sys = require("sys");
|
|
||||||
var fs = require("fs");
|
|
||||||
var PEG = require("../lib/peg");
|
|
||||||
|
|
||||||
/* Helpers */
|
|
||||||
|
|
||||||
function printVersion() {
|
|
||||||
sys.puts("PEG.js " + PEG.VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printHelp() {
|
|
||||||
sys.puts("Usage: pegjs [options] [--] [<input_file>] [<output_file>]");
|
|
||||||
sys.puts("");
|
|
||||||
sys.puts("Generates a parser from the PEG grammar specified in the <input_file> and");
|
|
||||||
sys.puts("writes it to the <output_file>.");
|
|
||||||
sys.puts("");
|
|
||||||
sys.puts("If the <output_file> is omitted, its name is generated by changing the");
|
|
||||||
sys.puts("<input_file> extension to \".js\". If both <input_file> and <output_file> are");
|
|
||||||
sys.puts("omitted, standard input and output are used.");
|
|
||||||
sys.puts("");
|
|
||||||
sys.puts("Options:");
|
|
||||||
sys.puts(" -e, --export-var <variable> name of the variable where the parser object");
|
|
||||||
sys.puts(" will be stored (default: \"module.exports\")");
|
|
||||||
sys.puts(" -v, --version print version information and exit");
|
|
||||||
sys.puts(" -h, --help print help and exit");
|
|
||||||
}
|
|
||||||
|
|
||||||
function exitSuccess() {
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function exitFailure() {
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function abort(message) {
|
|
||||||
sys.error(message);
|
|
||||||
exitFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Arguments */
|
|
||||||
|
|
||||||
var args = process.argv.slice(2); // Trim "node" and the script path.
|
|
||||||
|
|
||||||
function isOption(arg) {
|
|
||||||
return /-.+/.test(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextArg() {
|
|
||||||
args.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Files */
|
|
||||||
|
|
||||||
function readStream(inputStream, callback) {
|
|
||||||
var input = "";
|
|
||||||
inputStream.on("data", function(data) { input += data; });
|
|
||||||
inputStream.on("end", function() { callback(input); });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main */
|
|
||||||
|
|
||||||
/* This makes the generated parser a CommonJS module by default. */
|
|
||||||
var exportVar = "module.exports";
|
|
||||||
|
|
||||||
while (args.length > 0 && isOption(args[0])) {
|
|
||||||
switch (args[0]) {
|
|
||||||
case "-e":
|
|
||||||
case "--export-var":
|
|
||||||
nextArg();
|
|
||||||
if (args.length === 0) {
|
|
||||||
abort("Missing parameter of the -e/--export-var option.");
|
|
||||||
}
|
|
||||||
exportVar = args[0];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-v":
|
|
||||||
case "--version":
|
|
||||||
printVersion();
|
|
||||||
exitSuccess();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-h":
|
|
||||||
case "--help":
|
|
||||||
printHelp();
|
|
||||||
exitSuccess();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "--":
|
|
||||||
nextArg();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort("Unknown option: " + args[0] + ".");
|
|
||||||
}
|
|
||||||
nextArg();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (args.length) {
|
|
||||||
case 0:
|
|
||||||
var inputStream = process.openStdin();
|
|
||||||
var outputStream = process.stdout;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
var inputFile = args[0];
|
|
||||||
var inputStream = fs.createReadStream(inputFile);
|
|
||||||
inputStream.on("error", function() {
|
|
||||||
abort("Can't read from file \"" + inputFile + "\".");
|
|
||||||
});
|
|
||||||
|
|
||||||
var outputFile = args.length == 1
|
|
||||||
? args[0].replace(/\.[^.]*$/, ".js")
|
|
||||||
: args[1];
|
|
||||||
var outputStream = fs.createWriteStream(outputFile);
|
|
||||||
outputStream.on("error", function() {
|
|
||||||
abort("Can't write to file \"" + outputFile + "\".");
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort("Too many arguments.");
|
|
||||||
}
|
|
||||||
|
|
||||||
readStream(inputStream, function(input) {
|
|
||||||
try {
|
|
||||||
var parser = PEG.buildParser(input);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.line !== undefined && e.column !== undefined) {
|
|
||||||
abort(e.line + ":" + e.column + ": " + e.message);
|
|
||||||
} else {
|
|
||||||
abort(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outputStream.write(exportVar + " = " + parser.toSource() + ";\n");
|
|
||||||
outputStream.end();
|
|
||||||
});
|
|
22
node_modules/pegjs/examples/arithmetics.pegjs
generated
vendored
22
node_modules/pegjs/examples/arithmetics.pegjs
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Classic example grammar, which recognizes simple arithmetic expressions like
|
|
||||||
* "2*(3+4)". The parser generated from this grammar then computes their value.
|
|
||||||
*/
|
|
||||||
|
|
||||||
start
|
|
||||||
= additive
|
|
||||||
|
|
||||||
additive
|
|
||||||
= left:multiplicative "+" right:additive { return left + right; }
|
|
||||||
/ multiplicative
|
|
||||||
|
|
||||||
multiplicative
|
|
||||||
= left:primary "*" right:multiplicative { return left * right; }
|
|
||||||
/ primary
|
|
||||||
|
|
||||||
primary
|
|
||||||
= integer
|
|
||||||
/ "(" additive:additive ")" { return additive; }
|
|
||||||
|
|
||||||
integer "integer"
|
|
||||||
= digits:[0-9]+ { return parseInt(digits.join(""), 10); }
|
|
554
node_modules/pegjs/examples/css.pegjs
generated
vendored
554
node_modules/pegjs/examples/css.pegjs
generated
vendored
@ -1,554 +0,0 @@
|
|||||||
/*
|
|
||||||
* CSS parser based on the grammar described at http://www.w3.org/TR/CSS2/grammar.html.
|
|
||||||
*
|
|
||||||
* The parser builds a tree representing the parsed CSS, composed of basic
|
|
||||||
* JavaScript values, arrays and objects (basically JSON). It can be easily
|
|
||||||
* used by various CSS processors, transformers, etc.
|
|
||||||
*
|
|
||||||
* Note that the parser does not handle errors in CSS according to the
|
|
||||||
* specification -- many errors which it should recover from (e.g. malformed
|
|
||||||
* declarations or unexpected end of stylesheet) are simply fatal. This is a
|
|
||||||
* result of straightforward rewrite of the CSS grammar to PEG.js and it should
|
|
||||||
* be fixed sometimes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ===== Syntactical Elements ===== */
|
|
||||||
|
|
||||||
start
|
|
||||||
= stylesheet:stylesheet comment* { return stylesheet; }
|
|
||||||
|
|
||||||
stylesheet
|
|
||||||
= charset:(CHARSET_SYM STRING ";")? (S / CDO / CDC)*
|
|
||||||
imports:(import (CDO S* / CDC S*)*)*
|
|
||||||
rules:((ruleset / media / page) (CDO S* / CDC S*)*)* {
|
|
||||||
var importsConverted = [];
|
|
||||||
for (var i = 0; i < imports.length; i++) {
|
|
||||||
importsConverted.push(imports[i][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rulesConverted = [];
|
|
||||||
for (i = 0; i < rules.length; i++) {
|
|
||||||
rulesConverted.push(rules[i][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "stylesheet",
|
|
||||||
charset: charset !== "" ? charset[1] : null,
|
|
||||||
imports: importsConverted,
|
|
||||||
rules: rulesConverted
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
import
|
|
||||||
= IMPORT_SYM S* href:(STRING / URI) S* media:media_list? ";" S* {
|
|
||||||
return {
|
|
||||||
type: "import_rule",
|
|
||||||
href: href,
|
|
||||||
media: media !== "" ? media : []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
media
|
|
||||||
= MEDIA_SYM S* media:media_list "{" S* rules:ruleset* "}" S* {
|
|
||||||
return {
|
|
||||||
type: "media_rule",
|
|
||||||
media: media,
|
|
||||||
rules: rules
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
media_list
|
|
||||||
= head:medium tail:("," S* medium)* {
|
|
||||||
var result = [head];
|
|
||||||
for (var i = 0; i < tail.length; i++) {
|
|
||||||
result.push(tail[i][2]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
medium
|
|
||||||
= ident:IDENT S* { return ident; }
|
|
||||||
|
|
||||||
page
|
|
||||||
= PAGE_SYM S* qualifier:pseudo_page?
|
|
||||||
"{" S*
|
|
||||||
declarationsHead:declaration?
|
|
||||||
declarationsTail:(";" S* declaration?)*
|
|
||||||
"}" S* {
|
|
||||||
var declarations = declarationsHead !== "" ? [declarationsHead] : [];
|
|
||||||
for (var i = 0; i < declarationsTail.length; i++) {
|
|
||||||
if (declarationsTail[i][2] !== "") {
|
|
||||||
declarations.push(declarationsTail[i][2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "page_rule",
|
|
||||||
qualifier: qualifier !== "" ? qualifier : null,
|
|
||||||
declarations: declarations
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pseudo_page
|
|
||||||
= ":" ident:IDENT S* { return ident; }
|
|
||||||
|
|
||||||
operator
|
|
||||||
= "/" S* { return "/"; }
|
|
||||||
/ "," S* { return ","; }
|
|
||||||
|
|
||||||
combinator
|
|
||||||
= "+" S* { return "+"; }
|
|
||||||
/ ">" S* { return ">"; }
|
|
||||||
|
|
||||||
unary_operator
|
|
||||||
= "+"
|
|
||||||
/ "-"
|
|
||||||
|
|
||||||
property
|
|
||||||
= ident:IDENT S* { return ident; }
|
|
||||||
|
|
||||||
ruleset
|
|
||||||
= selectorsHead:selector
|
|
||||||
selectorsTail:("," S* selector)*
|
|
||||||
"{" S*
|
|
||||||
declarationsHead:declaration?
|
|
||||||
declarationsTail:(";" S* declaration?)*
|
|
||||||
"}" S* {
|
|
||||||
var selectors = [selectorsHead];
|
|
||||||
for (var i = 0; i < selectorsTail.length; i++) {
|
|
||||||
selectors.push(selectorsTail[i][2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var declarations = declarationsHead !== "" ? [declarationsHead] : [];
|
|
||||||
for (i = 0; i < declarationsTail.length; i++) {
|
|
||||||
if (declarationsTail[i][2] !== "") {
|
|
||||||
declarations.push(declarationsTail[i][2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "ruleset",
|
|
||||||
selectors: selectors,
|
|
||||||
declarations: declarations
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
selector
|
|
||||||
= left:simple_selector S* combinator:combinator right:selector {
|
|
||||||
return {
|
|
||||||
type: "selector",
|
|
||||||
combinator: combinator,
|
|
||||||
left: left,
|
|
||||||
right: right
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/ left:simple_selector S* right:selector {
|
|
||||||
return {
|
|
||||||
type: "selector",
|
|
||||||
combinator: " ",
|
|
||||||
left: left,
|
|
||||||
right: right
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/ selector:simple_selector S* { return selector; }
|
|
||||||
|
|
||||||
simple_selector
|
|
||||||
= element:element_name
|
|
||||||
qualifiers:(
|
|
||||||
id:HASH { return { type: "ID selector", id: id.substr(1) }; }
|
|
||||||
/ class
|
|
||||||
/ attrib
|
|
||||||
/ pseudo
|
|
||||||
)* {
|
|
||||||
return {
|
|
||||||
type: "simple_selector",
|
|
||||||
element: element,
|
|
||||||
qualifiers: qualifiers
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/ qualifiers:(
|
|
||||||
id:HASH { return { type: "ID selector", id: id.substr(1) }; }
|
|
||||||
/ class
|
|
||||||
/ attrib
|
|
||||||
/ pseudo
|
|
||||||
)+ {
|
|
||||||
return {
|
|
||||||
type: "simple_selector",
|
|
||||||
element: "*",
|
|
||||||
qualifiers: qualifiers
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class
|
|
||||||
= "." class_:IDENT { return { type: "class_selector", "class": class_ }; }
|
|
||||||
|
|
||||||
element_name
|
|
||||||
= IDENT / '*'
|
|
||||||
|
|
||||||
attrib
|
|
||||||
= "[" S*
|
|
||||||
attribute:IDENT S*
|
|
||||||
operatorAndValue:(
|
|
||||||
('=' / INCLUDES / DASHMATCH) S*
|
|
||||||
(IDENT / STRING) S*
|
|
||||||
)?
|
|
||||||
"]" {
|
|
||||||
return {
|
|
||||||
type: "attribute_selector",
|
|
||||||
attribute: attribute,
|
|
||||||
operator: operatorAndValue !== "" ? operatorAndValue[0] : null,
|
|
||||||
value: operatorAndValue !== "" ? operatorAndValue[2] : null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pseudo
|
|
||||||
= ":"
|
|
||||||
value:(
|
|
||||||
name:FUNCTION S* params:(IDENT S*)? ")" {
|
|
||||||
return {
|
|
||||||
type: "function",
|
|
||||||
name: name,
|
|
||||||
params: params !== "" ? [params[0]] : []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/ IDENT
|
|
||||||
) {
|
|
||||||
/*
|
|
||||||
* The returned object has somewhat vague property names and values because
|
|
||||||
* the rule matches both pseudo-classes and pseudo-elements (they look the
|
|
||||||
* same at the syntactic level).
|
|
||||||
*/
|
|
||||||
return {
|
|
||||||
type: "pseudo_selector",
|
|
||||||
value: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
declaration
|
|
||||||
= property:property ":" S* expression:expr important:prio? {
|
|
||||||
return {
|
|
||||||
type: "declaration",
|
|
||||||
property: property,
|
|
||||||
expression: expression,
|
|
||||||
important: important !== "" ? true : false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
prio
|
|
||||||
= IMPORTANT_SYM S*
|
|
||||||
|
|
||||||
expr
|
|
||||||
= head:term tail:(operator? term)* {
|
|
||||||
var result = head;
|
|
||||||
for (var i = 0; i < tail.length; i++) {
|
|
||||||
result = {
|
|
||||||
type: "expression",
|
|
||||||
operator: tail[i][0],
|
|
||||||
left: result,
|
|
||||||
right: tail[i][1]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
term
|
|
||||||
= operator:unary_operator?
|
|
||||||
value:(
|
|
||||||
EMS S*
|
|
||||||
/ EXS S*
|
|
||||||
/ LENGTH S*
|
|
||||||
/ ANGLE S*
|
|
||||||
/ TIME S*
|
|
||||||
/ FREQ S*
|
|
||||||
/ PERCENTAGE S*
|
|
||||||
/ NUMBER S*
|
|
||||||
) { return { type: "value", value: operator + value[0] }; }
|
|
||||||
/ value:URI S* { return { type: "uri", value: value }; }
|
|
||||||
/ function
|
|
||||||
/ hexcolor
|
|
||||||
/ value:STRING S* { return { type: "string", value: value }; }
|
|
||||||
/ value:IDENT S* { return { type: "ident", value: value }; }
|
|
||||||
|
|
||||||
function
|
|
||||||
= name:FUNCTION S* params:expr ")" S* {
|
|
||||||
return {
|
|
||||||
type: "function",
|
|
||||||
name: name,
|
|
||||||
params: params
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
hexcolor
|
|
||||||
= value:HASH S* { return { type: "hexcolor", value: value}; }
|
|
||||||
|
|
||||||
/* ===== Lexical Elements ===== */
|
|
||||||
|
|
||||||
/* Macros */
|
|
||||||
|
|
||||||
h
|
|
||||||
= [0-9a-fA-F]
|
|
||||||
|
|
||||||
nonascii
|
|
||||||
= [\x80-\xFF]
|
|
||||||
|
|
||||||
unicode
|
|
||||||
= "\\" h1:h h2:h? h3:h? h4:h? h5:h? h6:h? ("\r\n" / [ \t\r\n\f])? {
|
|
||||||
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4 + h5 + h6));
|
|
||||||
}
|
|
||||||
|
|
||||||
escape
|
|
||||||
= unicode
|
|
||||||
/ "\\" char_:[^\r\n\f0-9a-fA-F] { return char_; }
|
|
||||||
|
|
||||||
nmstart
|
|
||||||
= [_a-zA-Z]
|
|
||||||
/ nonascii
|
|
||||||
/ escape
|
|
||||||
|
|
||||||
nmchar
|
|
||||||
= [_a-zA-Z0-9-]
|
|
||||||
/ nonascii
|
|
||||||
/ escape
|
|
||||||
|
|
||||||
integer
|
|
||||||
= digits:[0-9]+ { return parseInt(digits.join("")); }
|
|
||||||
|
|
||||||
float
|
|
||||||
= before:[0-9]* "." after:[0-9]+ {
|
|
||||||
return parseFloat(before.join("") + "." + after.join(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
string1
|
|
||||||
= '"' chars:([^\n\r\f\\"] / "\\" nl:nl { return nl } / escape)* '"' {
|
|
||||||
return chars.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
string2
|
|
||||||
= "'" chars:([^\n\r\f\\'] / "\\" nl:nl { return nl } / escape)* "'" {
|
|
||||||
return chars.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
comment
|
|
||||||
= "/*" [^*]* "*"+ ([^/*] [^*]* "*"+)* "/"
|
|
||||||
|
|
||||||
ident
|
|
||||||
= dash:"-"? nmstart:nmstart nmchars:nmchar* {
|
|
||||||
return dash + nmstart + nmchars.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
name
|
|
||||||
= nmchars:nmchar+ { return nmchars.join(""); }
|
|
||||||
|
|
||||||
num
|
|
||||||
= float
|
|
||||||
/ integer
|
|
||||||
|
|
||||||
string
|
|
||||||
= string1
|
|
||||||
/ string2
|
|
||||||
|
|
||||||
url
|
|
||||||
= chars:([!#$%&*-~] / nonascii / escape)* { return chars.join(""); }
|
|
||||||
|
|
||||||
s
|
|
||||||
= [ \t\r\n\f]+
|
|
||||||
|
|
||||||
w
|
|
||||||
= s?
|
|
||||||
|
|
||||||
nl
|
|
||||||
= "\n"
|
|
||||||
/ "\r\n"
|
|
||||||
/ "\r"
|
|
||||||
/ "\f"
|
|
||||||
|
|
||||||
A
|
|
||||||
= [aA]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "41" ("\r\n" / [ \t\r\n\f])? { return "A"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "61" ("\r\n" / [ \t\r\n\f])? { return "a"; }
|
|
||||||
|
|
||||||
C
|
|
||||||
= [cC]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "43" ("\r\n" / [ \t\r\n\f])? { return "C"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "63" ("\r\n" / [ \t\r\n\f])? { return "c"; }
|
|
||||||
|
|
||||||
D
|
|
||||||
= [dD]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "44" ("\r\n" / [ \t\r\n\f])? { return "D"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "64" ("\r\n" / [ \t\r\n\f])? { return "d"; }
|
|
||||||
|
|
||||||
E
|
|
||||||
= [eE]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "45" ("\r\n" / [ \t\r\n\f])? { return "E"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "65" ("\r\n" / [ \t\r\n\f])? { return "e"; }
|
|
||||||
|
|
||||||
G
|
|
||||||
= [gG]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "47" ("\r\n" / [ \t\r\n\f])? { return "G"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "67" ("\r\n" / [ \t\r\n\f])? { return "g"; }
|
|
||||||
/ "\\" char_:[gG] { return char_; }
|
|
||||||
|
|
||||||
H
|
|
||||||
= h:[hH]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "48" ("\r\n" / [ \t\r\n\f])? { return "H"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "68" ("\r\n" / [ \t\r\n\f])? { return "h"; }
|
|
||||||
/ "\\" char_:[hH] { return char_; }
|
|
||||||
|
|
||||||
I
|
|
||||||
= i:[iI]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "49" ("\r\n" / [ \t\r\n\f])? { return "I"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "69" ("\r\n" / [ \t\r\n\f])? { return "i"; }
|
|
||||||
/ "\\" char_:[iI] { return char_; }
|
|
||||||
|
|
||||||
K
|
|
||||||
= [kK]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "4" [bB] ("\r\n" / [ \t\r\n\f])? { return "K"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "6" [bB] ("\r\n" / [ \t\r\n\f])? { return "k"; }
|
|
||||||
/ "\\" char_:[kK] { return char_; }
|
|
||||||
|
|
||||||
L
|
|
||||||
= [lL]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "4" [cC] ("\r\n" / [ \t\r\n\f])? { return "L"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "6" [cC] ("\r\n" / [ \t\r\n\f])? { return "l"; }
|
|
||||||
/ "\\" char_:[lL] { return char_; }
|
|
||||||
|
|
||||||
M
|
|
||||||
= [mM]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "4" [dD] ("\r\n" / [ \t\r\n\f])? { return "M"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "6" [dD] ("\r\n" / [ \t\r\n\f])? { return "m"; }
|
|
||||||
/ "\\" char_:[mM] { return char_; }
|
|
||||||
|
|
||||||
N
|
|
||||||
= [nN]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "4" [eE] ("\r\n" / [ \t\r\n\f])? { return "N"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "6" [eE] ("\r\n" / [ \t\r\n\f])? { return "n"; }
|
|
||||||
/ "\\" char_:[nN] { return char_; }
|
|
||||||
|
|
||||||
O
|
|
||||||
= [oO]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "4" [fF] ("\r\n" / [ \t\r\n\f])? { return "O"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "6" [fF] ("\r\n" / [ \t\r\n\f])? { return "o"; }
|
|
||||||
/ "\\" char_:[oO] { return char_; }
|
|
||||||
|
|
||||||
P
|
|
||||||
= [pP]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "50" ("\r\n" / [ \t\r\n\f])? { return "P"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "70" ("\r\n" / [ \t\r\n\f])? { return "p"; }
|
|
||||||
/ "\\" char_:[pP] { return char_; }
|
|
||||||
|
|
||||||
R
|
|
||||||
= [rR]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "52" ("\r\n" / [ \t\r\n\f])? { return "R"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "72" ("\r\n" / [ \t\r\n\f])? { return "r"; }
|
|
||||||
/ "\\" char_:[rR] { return char_; }
|
|
||||||
|
|
||||||
S_
|
|
||||||
= [sS]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "53" ("\r\n" / [ \t\r\n\f])? { return "S"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "73" ("\r\n" / [ \t\r\n\f])? { return "s"; }
|
|
||||||
/ "\\" char_:[sS] { return char_; }
|
|
||||||
|
|
||||||
T
|
|
||||||
= [tT]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "54" ("\r\n" / [ \t\r\n\f])? { return "T"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "74" ("\r\n" / [ \t\r\n\f])? { return "t"; }
|
|
||||||
/ "\\" char_:[tT] { return char_; }
|
|
||||||
|
|
||||||
U
|
|
||||||
= [uU]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "55" ("\r\n" / [ \t\r\n\f])? { return "U"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "75" ("\r\n" / [ \t\r\n\f])? { return "u"; }
|
|
||||||
/ "\\" char_:[uU] { return char_; }
|
|
||||||
|
|
||||||
X
|
|
||||||
= [xX]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "58" ("\r\n" / [ \t\r\n\f])? { return "X"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "78" ("\r\n" / [ \t\r\n\f])? { return "x"; }
|
|
||||||
/ "\\" char_:[xX] { return char_; }
|
|
||||||
|
|
||||||
Z
|
|
||||||
= [zZ]
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "5" [aA] ("\r\n" / [ \t\r\n\f])? { return "Z"; }
|
|
||||||
/ "\\" "0"? "0"? "0"? "0"? "7" [aA] ("\r\n" / [ \t\r\n\f])? { return "z"; }
|
|
||||||
/ "\\" char_:[zZ] { return char_; }
|
|
||||||
|
|
||||||
/* Tokens */
|
|
||||||
|
|
||||||
S "whitespace"
|
|
||||||
= comment* s
|
|
||||||
|
|
||||||
CDO "<!--"
|
|
||||||
= comment* "<!--"
|
|
||||||
|
|
||||||
CDC "-->"
|
|
||||||
= comment* "-->"
|
|
||||||
|
|
||||||
INCLUDES "~="
|
|
||||||
= comment* "~="
|
|
||||||
|
|
||||||
DASHMATCH "|="
|
|
||||||
= comment* "|="
|
|
||||||
|
|
||||||
STRING "string"
|
|
||||||
= comment* string:string { return string; }
|
|
||||||
|
|
||||||
IDENT "identifier"
|
|
||||||
= comment* ident:ident { return ident; }
|
|
||||||
|
|
||||||
HASH "hash"
|
|
||||||
= comment* "#" name:name { return "#" + name; }
|
|
||||||
|
|
||||||
IMPORT_SYM "@import"
|
|
||||||
= comment* "@" I M P O R T
|
|
||||||
|
|
||||||
PAGE_SYM "@page"
|
|
||||||
= comment* "@" P A G E
|
|
||||||
|
|
||||||
MEDIA_SYM "@media"
|
|
||||||
= comment* "@" M E D I A
|
|
||||||
|
|
||||||
CHARSET_SYM "@charset"
|
|
||||||
= comment* "@charset "
|
|
||||||
|
|
||||||
/* Note: We replace "w" with "s" here to avoid infinite recursion. */
|
|
||||||
IMPORTANT_SYM "!important"
|
|
||||||
= comment* "!" (s / comment)* I M P O R T A N T { return "!important"; }
|
|
||||||
|
|
||||||
EMS "length"
|
|
||||||
= comment* num:num e:E m:M { return num + e + m; }
|
|
||||||
|
|
||||||
EXS "length"
|
|
||||||
= comment* num:num e:E x:X { return num + e + x; }
|
|
||||||
|
|
||||||
LENGTH "length"
|
|
||||||
= comment* num:num unit:(P X / C M / M M / I N / P T / P C) {
|
|
||||||
return num + unit.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
ANGLE "angle"
|
|
||||||
= comment* num:num unit:(D E G / R A D / G R A D) {
|
|
||||||
return num + unit.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
TIME "time"
|
|
||||||
= comment* num:num unit:(m:M s:S_ { return m + s; } / S_) {
|
|
||||||
return num + unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
FREQ "frequency"
|
|
||||||
= comment* num:num unit:(H Z / K H Z) { return num + unit.join(""); }
|
|
||||||
|
|
||||||
DIMENSION "dimension"
|
|
||||||
= comment* num:num unit:ident { return num + unit; }
|
|
||||||
|
|
||||||
PERCENTAGE "percentage"
|
|
||||||
= comment* num:num "%" { return num + "%"; }
|
|
||||||
|
|
||||||
NUMBER "number"
|
|
||||||
= comment* num:num { return num; }
|
|
||||||
|
|
||||||
URI "uri"
|
|
||||||
= comment* U R L "(" w value:(string / url) w ")" { return value; }
|
|
||||||
|
|
||||||
FUNCTION "function"
|
|
||||||
= comment* name:ident "(" { return name; }
|
|
1530
node_modules/pegjs/examples/javascript.pegjs
generated
vendored
1530
node_modules/pegjs/examples/javascript.pegjs
generated
vendored
File diff suppressed because one or more lines are too long
120
node_modules/pegjs/examples/json.pegjs
generated
vendored
120
node_modules/pegjs/examples/json.pegjs
generated
vendored
@ -1,120 +0,0 @@
|
|||||||
/* JSON parser based on the grammar described at http://json.org/. */
|
|
||||||
|
|
||||||
/* ===== Syntactical Elements ===== */
|
|
||||||
|
|
||||||
start
|
|
||||||
= _ object:object { return object; }
|
|
||||||
|
|
||||||
object
|
|
||||||
= "{" _ "}" _ { return {}; }
|
|
||||||
/ "{" _ members:members "}" _ { return members; }
|
|
||||||
|
|
||||||
members
|
|
||||||
= head:pair tail:("," _ pair)* {
|
|
||||||
var result = {};
|
|
||||||
result[head[0]] = head[1];
|
|
||||||
for (var i = 0; i < tail.length; i++) {
|
|
||||||
result[tail[i][2][0]] = tail[i][2][1];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pair
|
|
||||||
= name:string ":" _ value:value { return [name, value]; }
|
|
||||||
|
|
||||||
array
|
|
||||||
= "[" _ "]" _ { return []; }
|
|
||||||
/ "[" _ elements:elements "]" _ { return elements; }
|
|
||||||
|
|
||||||
elements
|
|
||||||
= head:value tail:("," _ value)* {
|
|
||||||
var result = [head];
|
|
||||||
for (var i = 0; i < tail.length; i++) {
|
|
||||||
result.push(tail[i][2]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
value
|
|
||||||
= string
|
|
||||||
/ number
|
|
||||||
/ object
|
|
||||||
/ array
|
|
||||||
/ "true" _ { return true; }
|
|
||||||
/ "false" _ { return false; }
|
|
||||||
// FIXME: We can't return null here because that would mean parse failure.
|
|
||||||
/ "null" _ { return "null"; }
|
|
||||||
|
|
||||||
/* ===== Lexical Elements ===== */
|
|
||||||
|
|
||||||
string "string"
|
|
||||||
= '"' '"' _ { return ""; }
|
|
||||||
/ '"' chars:chars '"' _ { return chars; }
|
|
||||||
|
|
||||||
chars
|
|
||||||
= chars:char+ { return chars.join(""); }
|
|
||||||
|
|
||||||
char
|
|
||||||
// In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character"
|
|
||||||
= [^"\\\0-\x1F\x7f]
|
|
||||||
/ '\\"' { return '"'; }
|
|
||||||
/ "\\\\" { return "\\"; }
|
|
||||||
/ "\\/" { return "/"; }
|
|
||||||
/ "\\b" { return "\b"; }
|
|
||||||
/ "\\f" { return "\f"; }
|
|
||||||
/ "\\n" { return "\n"; }
|
|
||||||
/ "\\r" { return "\r"; }
|
|
||||||
/ "\\t" { return "\t"; }
|
|
||||||
/ "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit {
|
|
||||||
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
|
|
||||||
}
|
|
||||||
|
|
||||||
number "number"
|
|
||||||
= int_:int frac:frac exp:exp _ { return parseFloat(int_ + frac + exp); }
|
|
||||||
/ int_:int frac:frac _ { return parseFloat(int_ + frac); }
|
|
||||||
/ int_:int exp:exp _ { return parseFloat(int_ + exp); }
|
|
||||||
/ int_:int _ { return parseFloat(int_); }
|
|
||||||
|
|
||||||
int
|
|
||||||
= digit19:digit19 digits:digits { return digit19 + digits; }
|
|
||||||
/ digit:digit
|
|
||||||
/ "-" digit19:digit19 digits:digits { return "-" + digit19 + digits; }
|
|
||||||
/ "-" digit:digit { return "-" + digit; }
|
|
||||||
|
|
||||||
frac
|
|
||||||
= "." digits:digits { return "." + digits; }
|
|
||||||
|
|
||||||
exp
|
|
||||||
= e:e digits:digits { return e + digits; }
|
|
||||||
|
|
||||||
digits
|
|
||||||
= digits:digit+ { return digits.join(""); }
|
|
||||||
|
|
||||||
e
|
|
||||||
= e:[eE] sign:[+-]? { return e + sign; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following rules are not present in the original JSON gramar, but they are
|
|
||||||
* assumed to exist implicitly.
|
|
||||||
*
|
|
||||||
* FIXME: Define them according to ECMA-262, 5th ed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
digit
|
|
||||||
= [0-9]
|
|
||||||
|
|
||||||
digit19
|
|
||||||
= [1-9]
|
|
||||||
|
|
||||||
hexDigit
|
|
||||||
= [0-9a-fA-F]
|
|
||||||
|
|
||||||
/* ===== Whitespace ===== */
|
|
||||||
|
|
||||||
_ "whitespace"
|
|
||||||
= whitespace*
|
|
||||||
|
|
||||||
// Whitespace is undefined in the original JSON grammar, so I assume a simple
|
|
||||||
// conventional definition consistent with ECMA-262, 5th ed.
|
|
||||||
whitespace
|
|
||||||
= [ \t\n\r]
|
|
5141
node_modules/pegjs/lib/peg.js
generated
vendored
5141
node_modules/pegjs/lib/peg.js
generated
vendored
File diff suppressed because it is too large
Load Diff
24
node_modules/pegjs/package.json
generated
vendored
24
node_modules/pegjs/package.json
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "pegjs",
|
|
||||||
"version": "0.6.2",
|
|
||||||
"description": "Parser generator for JavaScript",
|
|
||||||
"homepage": "http://pegjs.majda.cz/",
|
|
||||||
"author": {
|
|
||||||
"name": "David Majda",
|
|
||||||
"email": "david@majda.cz",
|
|
||||||
"url": "http://majda.cz/"
|
|
||||||
},
|
|
||||||
"main": "lib/peg",
|
|
||||||
"bin": "bin/pegjs",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/dmajda/pegjs.git"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"jake": ">= 0.1.10",
|
|
||||||
"uglify-js": ">= 0.0.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.4"
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,8 +15,8 @@ jsmodule: ../js/*.js
|
|||||||
|
|
||||||
jsmodule: ../js/macros/*.js
|
jsmodule: ../js/macros/*.js
|
||||||
|
|
||||||
jsmodule: ../node_modules/pegjs/lib/peg.js
|
jsmodule: ../node_modules/esprima/esprima.js
|
||||||
title: pegjs
|
title: esprima
|
||||||
|
|
||||||
jsbootstart: BootStart.js
|
jsbootstart: BootStart.js
|
||||||
jsbootend: BootLoader.js
|
jsbootend: BootLoader.js
|
||||||
|
Loading…
x
Reference in New Issue
Block a user