[Pkg-javascript-commits] [node-esutils] 01/09: Import Upstream version 2.0.2
Praveen Arimbrathodiyil
praveen at moszumanska.debian.org
Mon Oct 10 10:09:27 UTC 2016
This is an automated email from the git hooks/post-receive script.
praveen pushed a commit to branch master
in repository node-esutils.
commit d3b1ed0dcf8a73b65352c4d28309cc09c58bfb57
Author: Praveen Arimbrathodiyil <praveen at debian.org>
Date: Mon Oct 10 15:04:16 2016 +0530
Import Upstream version 2.0.2
---
.gitignore | 1 +
.jshintrc | 16 ++
.travis.yml | 8 +
LICENSE.BSD | 19 ++
README.md | 169 ++++++++++++++++
lib/ast.js | 144 +++++++++++++
lib/code.js | 135 +++++++++++++
lib/keyword.js | 165 +++++++++++++++
lib/utils.js | 33 +++
package.json | 49 +++++
test/ast.coffee | 175 ++++++++++++++++
test/code.coffee | 183 +++++++++++++++++
test/keyword.coffee | 400 +++++++++++++++++++++++++++++++++++++
tools/generate-identifier-regex.js | 87 ++++++++
14 files changed, 1584 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..f642dae
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,16 @@
+{
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "eqnull": true,
+ "latedef": true,
+ "noarg": true,
+ "noempty": true,
+ "quotmark": "single",
+ "undef": true,
+ "unused": true,
+ "strict": true,
+ "trailing": true,
+
+ "node": true
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..4b59f8d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+ - "0.10"
+ - "0.11"
+
+matrix:
+ allow_failures:
+ - node_js: "0.11"
diff --git a/LICENSE.BSD b/LICENSE.BSD
new file mode 100644
index 0000000..3e580c3
--- /dev/null
+++ b/LICENSE.BSD
@@ -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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..610d8bd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,169 @@
+### esutils [![Build Status](https://secure.travis-ci.org/estools/esutils.svg)](http://travis-ci.org/estools/esutils)
+esutils ([esutils](http://github.com/estools/esutils)) is
+utility box for ECMAScript language tools.
+
+### API
+
+### ast
+
+#### ast.isExpression(node)
+
+Returns true if `node` is an Expression as defined in ECMA262 edition 5.1 section
+[11](https://es5.github.io/#x11).
+
+#### ast.isStatement(node)
+
+Returns true if `node` is a Statement as defined in ECMA262 edition 5.1 section
+[12](https://es5.github.io/#x12).
+
+#### ast.isIterationStatement(node)
+
+Returns true if `node` is an IterationStatement as defined in ECMA262 edition
+5.1 section [12.6](https://es5.github.io/#x12.6).
+
+#### ast.isSourceElement(node)
+
+Returns true if `node` is a SourceElement as defined in ECMA262 edition 5.1
+section [14](https://es5.github.io/#x14).
+
+#### ast.trailingStatement(node)
+
+Returns `Statement?` if `node` has trailing `Statement`.
+```js
+if (cond)
+ consequent;
+```
+When taking this `IfStatement`, returns `consequent;` statement.
+
+#### ast.isProblematicIfStatement(node)
+
+Returns true if `node` is a problematic IfStatement. If `node` is a problematic `IfStatement`, `node` cannot be represented as an one on one JavaScript code.
+```js
+{
+ type: 'IfStatement',
+ consequent: {
+ type: 'WithStatement',
+ body: {
+ type: 'IfStatement',
+ consequent: {type: 'EmptyStatement'}
+ }
+ },
+ alternate: {type: 'EmptyStatement'}
+}
+```
+The above node cannot be represented as a JavaScript code, since the top level `else` alternate belongs to an inner `IfStatement`.
+
+
+### code
+
+#### code.isDecimalDigit(code)
+
+Return true if provided code is decimal digit.
+
+#### code.isHexDigit(code)
+
+Return true if provided code is hexadecimal digit.
+
+#### code.isOctalDigit(code)
+
+Return true if provided code is octal digit.
+
+#### code.isWhiteSpace(code)
+
+Return true if provided code is white space. White space characters are formally defined in ECMA262.
+
+#### code.isLineTerminator(code)
+
+Return true if provided code is line terminator. Line terminator characters are formally defined in ECMA262.
+
+#### code.isIdentifierStart(code)
+
+Return true if provided code can be the first character of ECMA262 Identifier. They are formally defined in ECMA262.
+
+#### code.isIdentifierPart(code)
+
+Return true if provided code can be the trailing character of ECMA262 Identifier. They are formally defined in ECMA262.
+
+### keyword
+
+#### keyword.isKeywordES5(id, strict)
+
+Returns `true` if provided identifier string is a Keyword or Future Reserved Word
+in ECMA262 edition 5.1. They are formally defined in ECMA262 sections
+[7.6.1.1](http://es5.github.io/#x7.6.1.1) and [7.6.1.2](http://es5.github.io/#x7.6.1.2),
+respectively. If the `strict` flag is truthy, this function additionally checks whether
+`id` is a Keyword or Future Reserved Word under strict mode.
+
+#### keyword.isKeywordES6(id, strict)
+
+Returns `true` if provided identifier string is a Keyword or Future Reserved Word
+in ECMA262 edition 6. They are formally defined in ECMA262 sections
+[11.6.2.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-keywords) and
+[11.6.2.2](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-future-reserved-words),
+respectively. If the `strict` flag is truthy, this function additionally checks whether
+`id` is a Keyword or Future Reserved Word under strict mode.
+
+#### keyword.isReservedWordES5(id, strict)
+
+Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 5.1.
+They are formally defined in ECMA262 section [7.6.1](http://es5.github.io/#x7.6.1).
+If the `strict` flag is truthy, this function additionally checks whether `id`
+is a Reserved Word under strict mode.
+
+#### keyword.isReservedWordES6(id, strict)
+
+Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 6.
+They are formally defined in ECMA262 section [11.6.2](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reserved-words).
+If the `strict` flag is truthy, this function additionally checks whether `id`
+is a Reserved Word under strict mode.
+
+#### keyword.isRestrictedWord(id)
+
+Returns `true` if provided identifier string is one of `eval` or `arguments`.
+They are restricted in strict mode code throughout ECMA262 edition 5.1 and
+in ECMA262 edition 6 section [12.1.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifiers-static-semantics-early-errors).
+
+#### keyword.isIdentifierName(id)
+
+Return true if provided identifier string is an IdentifierName as specified in
+ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6).
+
+#### keyword.isIdentifierES5(id, strict)
+
+Return true if provided identifier string is an Identifier as specified in
+ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6). If the `strict`
+flag is truthy, this function additionally checks whether `id` is an Identifier
+under strict mode.
+
+#### keyword.isIdentifierES6(id, strict)
+
+Return true if provided identifier string is an Identifier as specified in
+ECMA262 edition 6 section [12.1](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifiers).
+If the `strict` flag is truthy, this function additionally checks whether `id`
+is an Identifier under strict mode.
+
+### License
+
+Copyright (C) 2013 [Yusuke Suzuki](http://github.com/Constellation)
+ (twitter: [@Constellation](http://twitter.com/Constellation)) 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.
diff --git a/lib/ast.js b/lib/ast.js
new file mode 100644
index 0000000..8faadae
--- /dev/null
+++ b/lib/ast.js
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+*/
+
+(function () {
+ 'use strict';
+
+ function isExpression(node) {
+ if (node == null) { return false; }
+ switch (node.type) {
+ case 'ArrayExpression':
+ case 'AssignmentExpression':
+ case 'BinaryExpression':
+ case 'CallExpression':
+ case 'ConditionalExpression':
+ case 'FunctionExpression':
+ case 'Identifier':
+ case 'Literal':
+ case 'LogicalExpression':
+ case 'MemberExpression':
+ case 'NewExpression':
+ case 'ObjectExpression':
+ case 'SequenceExpression':
+ case 'ThisExpression':
+ case 'UnaryExpression':
+ case 'UpdateExpression':
+ return true;
+ }
+ return false;
+ }
+
+ function isIterationStatement(node) {
+ if (node == null) { return false; }
+ switch (node.type) {
+ case 'DoWhileStatement':
+ case 'ForInStatement':
+ case 'ForStatement':
+ case 'WhileStatement':
+ return true;
+ }
+ return false;
+ }
+
+ function isStatement(node) {
+ if (node == null) { return false; }
+ switch (node.type) {
+ case 'BlockStatement':
+ case 'BreakStatement':
+ case 'ContinueStatement':
+ case 'DebuggerStatement':
+ case 'DoWhileStatement':
+ case 'EmptyStatement':
+ case 'ExpressionStatement':
+ case 'ForInStatement':
+ case 'ForStatement':
+ case 'IfStatement':
+ case 'LabeledStatement':
+ case 'ReturnStatement':
+ case 'SwitchStatement':
+ case 'ThrowStatement':
+ case 'TryStatement':
+ case 'VariableDeclaration':
+ case 'WhileStatement':
+ case 'WithStatement':
+ return true;
+ }
+ return false;
+ }
+
+ function isSourceElement(node) {
+ return isStatement(node) || node != null && node.type === 'FunctionDeclaration';
+ }
+
+ function trailingStatement(node) {
+ switch (node.type) {
+ case 'IfStatement':
+ if (node.alternate != null) {
+ return node.alternate;
+ }
+ return node.consequent;
+
+ case 'LabeledStatement':
+ case 'ForStatement':
+ case 'ForInStatement':
+ case 'WhileStatement':
+ case 'WithStatement':
+ return node.body;
+ }
+ return null;
+ }
+
+ function isProblematicIfStatement(node) {
+ var current;
+
+ if (node.type !== 'IfStatement') {
+ return false;
+ }
+ if (node.alternate == null) {
+ return false;
+ }
+ current = node.consequent;
+ do {
+ if (current.type === 'IfStatement') {
+ if (current.alternate == null) {
+ return true;
+ }
+ }
+ current = trailingStatement(current);
+ } while (current);
+
+ return false;
+ }
+
+ module.exports = {
+ isExpression: isExpression,
+ isStatement: isStatement,
+ isIterationStatement: isIterationStatement,
+ isSourceElement: isSourceElement,
+ isProblematicIfStatement: isProblematicIfStatement,
+
+ trailingStatement: trailingStatement
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/lib/code.js b/lib/code.js
new file mode 100644
index 0000000..2a7c19d
--- /dev/null
+++ b/lib/code.js
@@ -0,0 +1,135 @@
+/*
+ Copyright (C) 2013-2014 Yusuke Suzuki <utatane.tea at gmail.com>
+ Copyright (C) 2014 Ivan Nikulin <ifaaan at 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.
+*/
+
+(function () {
+ 'use strict';
+
+ var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch;
+
+ // See `tools/generate-identifier-regex.js`.
+ ES5Regex = {
+ // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierStart:
+ NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u085 [...]
+ // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierPart:
+ NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u [...]
+ };
+
+ ES6Regex = {
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
+ NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u085 [...]
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
+ NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u08 [...]
+ };
+
+ function isDecimalDigit(ch) {
+ return 0x30 <= ch && ch <= 0x39; // 0..9
+ }
+
+ function isHexDigit(ch) {
+ return 0x30 <= ch && ch <= 0x39 || // 0..9
+ 0x61 <= ch && ch <= 0x66 || // a..f
+ 0x41 <= ch && ch <= 0x46; // A..F
+ }
+
+ function isOctalDigit(ch) {
+ return ch >= 0x30 && ch <= 0x37; // 0..7
+ }
+
+ // 7.2 White Space
+
+ NON_ASCII_WHITESPACES = [
+ 0x1680, 0x180E,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A,
+ 0x202F, 0x205F,
+ 0x3000,
+ 0xFEFF
+ ];
+
+ function isWhiteSpace(ch) {
+ return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 ||
+ ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0;
+ }
+
+ // 7.3 Line Terminators
+
+ function isLineTerminator(ch) {
+ return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029;
+ }
+
+ // 7.6 Identifier Names and Identifiers
+
+ function fromCodePoint(cp) {
+ if (cp <= 0xFFFF) { return String.fromCharCode(cp); }
+ var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800);
+ var cu2 = String.fromCharCode(((cp - 0x10000) % 0x400) + 0xDC00);
+ return cu1 + cu2;
+ }
+
+ IDENTIFIER_START = new Array(0x80);
+ for(ch = 0; ch < 0x80; ++ch) {
+ IDENTIFIER_START[ch] =
+ ch >= 0x61 && ch <= 0x7A || // a..z
+ ch >= 0x41 && ch <= 0x5A || // A..Z
+ ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore)
+ }
+
+ IDENTIFIER_PART = new Array(0x80);
+ for(ch = 0; ch < 0x80; ++ch) {
+ IDENTIFIER_PART[ch] =
+ ch >= 0x61 && ch <= 0x7A || // a..z
+ ch >= 0x41 && ch <= 0x5A || // A..Z
+ ch >= 0x30 && ch <= 0x39 || // 0..9
+ ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore)
+ }
+
+ function isIdentifierStartES5(ch) {
+ return ch < 0x80 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierPartES5(ch) {
+ return ch < 0x80 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierStartES6(ch) {
+ return ch < 0x80 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
+ }
+
+ function isIdentifierPartES6(ch) {
+ return ch < 0x80 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
+ }
+
+ module.exports = {
+ isDecimalDigit: isDecimalDigit,
+ isHexDigit: isHexDigit,
+ isOctalDigit: isOctalDigit,
+ isWhiteSpace: isWhiteSpace,
+ isLineTerminator: isLineTerminator,
+ isIdentifierStartES5: isIdentifierStartES5,
+ isIdentifierPartES5: isIdentifierPartES5,
+ isIdentifierStartES6: isIdentifierStartES6,
+ isIdentifierPartES6: isIdentifierPartES6
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/lib/keyword.js b/lib/keyword.js
new file mode 100644
index 0000000..13c8c6a
--- /dev/null
+++ b/lib/keyword.js
@@ -0,0 +1,165 @@
+/*
+ Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+*/
+
+(function () {
+ 'use strict';
+
+ var code = require('./code');
+
+ function isStrictModeReservedWordES6(id) {
+ switch (id) {
+ case 'implements':
+ case 'interface':
+ case 'package':
+ case 'private':
+ case 'protected':
+ case 'public':
+ case 'static':
+ case 'let':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isKeywordES5(id, strict) {
+ // yield should not be treated as keyword under non-strict mode.
+ if (!strict && id === 'yield') {
+ return false;
+ }
+ return isKeywordES6(id, strict);
+ }
+
+ function isKeywordES6(id, strict) {
+ if (strict && isStrictModeReservedWordES6(id)) {
+ return true;
+ }
+
+ switch (id.length) {
+ case 2:
+ return (id === 'if') || (id === 'in') || (id === 'do');
+ case 3:
+ return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
+ case 4:
+ return (id === 'this') || (id === 'else') || (id === 'case') ||
+ (id === 'void') || (id === 'with') || (id === 'enum');
+ case 5:
+ return (id === 'while') || (id === 'break') || (id === 'catch') ||
+ (id === 'throw') || (id === 'const') || (id === 'yield') ||
+ (id === 'class') || (id === 'super');
+ case 6:
+ return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
+ (id === 'switch') || (id === 'export') || (id === 'import');
+ case 7:
+ return (id === 'default') || (id === 'finally') || (id === 'extends');
+ case 8:
+ return (id === 'function') || (id === 'continue') || (id === 'debugger');
+ case 10:
+ return (id === 'instanceof');
+ default:
+ return false;
+ }
+ }
+
+ function isReservedWordES5(id, strict) {
+ return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict);
+ }
+
+ function isReservedWordES6(id, strict) {
+ return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict);
+ }
+
+ function isRestrictedWord(id) {
+ return id === 'eval' || id === 'arguments';
+ }
+
+ function isIdentifierNameES5(id) {
+ var i, iz, ch;
+
+ if (id.length === 0) { return false; }
+
+ ch = id.charCodeAt(0);
+ if (!code.isIdentifierStartES5(ch)) {
+ return false;
+ }
+
+ for (i = 1, iz = id.length; i < iz; ++i) {
+ ch = id.charCodeAt(i);
+ if (!code.isIdentifierPartES5(ch)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function decodeUtf16(lead, trail) {
+ return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
+ }
+
+ function isIdentifierNameES6(id) {
+ var i, iz, ch, lowCh, check;
+
+ if (id.length === 0) { return false; }
+
+ check = code.isIdentifierStartES6;
+ for (i = 0, iz = id.length; i < iz; ++i) {
+ ch = id.charCodeAt(i);
+ if (0xD800 <= ch && ch <= 0xDBFF) {
+ ++i;
+ if (i >= iz) { return false; }
+ lowCh = id.charCodeAt(i);
+ if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) {
+ return false;
+ }
+ ch = decodeUtf16(ch, lowCh);
+ }
+ if (!check(ch)) {
+ return false;
+ }
+ check = code.isIdentifierPartES6;
+ }
+ return true;
+ }
+
+ function isIdentifierES5(id, strict) {
+ return isIdentifierNameES5(id) && !isReservedWordES5(id, strict);
+ }
+
+ function isIdentifierES6(id, strict) {
+ return isIdentifierNameES6(id) && !isReservedWordES6(id, strict);
+ }
+
+ module.exports = {
+ isKeywordES5: isKeywordES5,
+ isKeywordES6: isKeywordES6,
+ isReservedWordES5: isReservedWordES5,
+ isReservedWordES6: isReservedWordES6,
+ isRestrictedWord: isRestrictedWord,
+ isIdentifierNameES5: isIdentifierNameES5,
+ isIdentifierNameES6: isIdentifierNameES6,
+ isIdentifierES5: isIdentifierES5,
+ isIdentifierES6: isIdentifierES6
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/lib/utils.js b/lib/utils.js
new file mode 100644
index 0000000..ce18faa
--- /dev/null
+++ b/lib/utils.js
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+*/
+
+
+(function () {
+ 'use strict';
+
+ exports.ast = require('./ast');
+ exports.code = require('./code');
+ exports.keyword = require('./keyword');
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ddce20b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "esutils",
+ "description": "utility box for ECMAScript language tools",
+ "homepage": "https://github.com/estools/esutils",
+ "main": "lib/utils.js",
+ "version": "2.0.2",
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "directories": {
+ "lib": "./lib"
+ },
+ "files": [
+ "LICENSE.BSD",
+ "README.md",
+ "lib"
+ ],
+ "maintainers": [
+ {
+ "name": "Yusuke Suzuki",
+ "email": "utatane.tea at gmail.com",
+ "web": "http://github.com/Constellation"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/estools/esutils.git"
+ },
+ "devDependencies": {
+ "chai": "~1.7.2",
+ "coffee-script": "~1.6.3",
+ "jshint": "2.6.3",
+ "mocha": "~2.2.1",
+ "regenerate": "~1.2.1",
+ "unicode-7.0.0": "^0.1.5"
+ },
+ "licenses": [
+ {
+ "type": "BSD",
+ "url": "http://github.com/estools/esutils/raw/master/LICENSE.BSD"
+ }
+ ],
+ "scripts": {
+ "test": "npm run-script lint && npm run-script unit-test",
+ "lint": "jshint lib/*.js",
+ "unit-test": "mocha --compilers coffee:coffee-script -R spec",
+ "generate-regex": "node tools/generate-identifier-regex.js"
+ }
+}
diff --git a/test/ast.coffee b/test/ast.coffee
new file mode 100644
index 0000000..021a7cd
--- /dev/null
+++ b/test/ast.coffee
@@ -0,0 +1,175 @@
+# Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+
+'use strict'
+
+expect = require('chai').expect
+esutils = require '../'
+
+EMPTY = {type: 'EmptyStatement'}
+
+describe 'ast', ->
+ describe 'isExpression', ->
+ it 'returns false if input is not node', ->
+ expect(esutils.ast.isExpression(0)).to.be.false
+ expect(esutils.ast.isExpression(null)).to.be.false
+ expect(esutils.ast.isExpression(undefined)).to.be.false
+ expect(esutils.ast.isExpression({})).to.be.false
+ expect(esutils.ast.isExpression({type: null})).to.be.false
+ expect(esutils.ast.isExpression({type: undefined})).to.be.false
+
+ it 'returns true if provided node is expression', ->
+ expect(esutils.ast.isExpression({type: "ThisExpression"})).to.be.true
+ expect(esutils.ast.isExpression({type: "Literal", value: 0})).to.be.true
+
+ it 'returns false if provided node is not expression', ->
+ expect(esutils.ast.isExpression({type: "ExpressionStatement"})).to.be.false
+ expect(esutils.ast.isExpression({type: "Program"})).to.be.false
+
+
+ describe 'isIterationStatement', ->
+ it 'returns false if input is not node', ->
+ expect(esutils.ast.isIterationStatement(0)).to.be.false
+ expect(esutils.ast.isIterationStatement(null)).to.be.false
+ expect(esutils.ast.isIterationStatement(undefined)).to.be.false
+ expect(esutils.ast.isIterationStatement({})).to.be.false
+ expect(esutils.ast.isIterationStatement({type: null})).to.be.false
+ expect(esutils.ast.isIterationStatement({type: undefined})).to.be.false
+
+ it 'returns true if provided node is iteration statement', ->
+ expect(esutils.ast.isIterationStatement({type: "ForInStatement"})).to.be.true
+ expect(esutils.ast.isIterationStatement({type: "DoWhileStatement"})).to.be.true
+
+ it 'returns false if provided node is not iteration statement', ->
+ expect(esutils.ast.isIterationStatement({type: "ExpressionStatement"})).to.be.false
+ expect(esutils.ast.isIterationStatement({type: "ThisExpression"})).to.be.false
+
+
+ describe 'isStatement', ->
+ it 'returns false if input is not node', ->
+ expect(esutils.ast.isStatement(0)).to.be.false
+ expect(esutils.ast.isStatement(null)).to.be.false
+ expect(esutils.ast.isStatement(undefined)).to.be.false
+ expect(esutils.ast.isStatement({})).to.be.false
+ expect(esutils.ast.isStatement({type: null})).to.be.false
+ expect(esutils.ast.isStatement({type: undefined})).to.be.false
+
+ it 'returns true if provided node is statement', ->
+ expect(esutils.ast.isStatement({type: "ExpressionStatement"})).to.be.true
+ expect(esutils.ast.isStatement({type: "WhileStatement"})).to.be.true
+
+ it 'returns false if provided node is not statement', ->
+ expect(esutils.ast.isStatement({type: "ThisExpression"})).to.be.false
+ expect(esutils.ast.isStatement({type: "FunctionDeclaration"})).to.be.false
+ expect(esutils.ast.isStatement({type: "Program"})).to.be.false
+
+
+ describe 'isSourceElement', ->
+ it 'returns false if input is not node', ->
+ expect(esutils.ast.isSourceElement(0)).to.be.false
+ expect(esutils.ast.isSourceElement(null)).to.be.false
+ expect(esutils.ast.isSourceElement(undefined)).to.be.false
+ expect(esutils.ast.isSourceElement({})).to.be.false
+ expect(esutils.ast.isSourceElement({type: null})).to.be.false
+ expect(esutils.ast.isSourceElement({type: undefined})).to.be.false
+
+ it 'returns true if provided node is source element', ->
+ expect(esutils.ast.isSourceElement({type: "ExpressionStatement"})).to.be.true
+ expect(esutils.ast.isSourceElement({type: "WhileStatement"})).to.be.true
+ expect(esutils.ast.isSourceElement({type: "FunctionDeclaration"})).to.be.true
+
+ it 'returns false if provided node is not source element', ->
+ expect(esutils.ast.isSourceElement({type: "ThisExpression"})).to.be.false
+ expect(esutils.ast.isSourceElement({type: "Program"})).to.be.false
+
+ describe 'trailingStatement', ->
+ it 'returns trailing statement if node has it', ->
+ expect(esutils.ast.trailingStatement({type: 'WhileStatement', body: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'WithStatement', body: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'ForStatement', body: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'ForInStatement', body: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'IfStatement', consequent: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'IfStatement', consequent: {type:'EmptyStatement'}, alternate: EMPTY})).to.be.eq EMPTY
+ expect(esutils.ast.trailingStatement({type: 'LabeledStatement', body: EMPTY})).to.be.eq EMPTY
+
+ it 'returns null if node doens\'t have trailing statement', ->
+ expect(esutils.ast.trailingStatement({type: 'DoWhileStatement', body: EMPTY})).to.be.null
+ expect(esutils.ast.trailingStatement({type: 'ReturnStatement' })).to.be.null
+
+ describe 'isProblematicIfStatement', ->
+ it 'returns true if node is problematic if statement', ->
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent: {
+ type: 'IfStatement'
+ consequent: EMPTY
+ }
+ alternate: EMPTY
+ )).to.be.true
+
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent:
+ type: 'LabeledStatement'
+ body:
+ type: 'IfStatement'
+ consequent: EMPTY
+ alternate: EMPTY
+ )).to.be.true
+
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent:
+ type: 'WithStatement'
+ body:
+ type: 'IfStatement'
+ consequent: EMPTY
+ alternate: EMPTY
+ )).to.be.true
+
+ it 'returns false if node is not problematic if statement', ->
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent: EMPTY
+ alternate: EMPTY
+ )).to.be.false
+
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent:
+ type: 'BlockStatement'
+ body: [
+ type: 'IfStatement'
+ consequent: EMPTY
+ ]
+ alternate: EMPTY
+ )).to.be.false
+
+ expect(esutils.ast.isProblematicIfStatement(
+ type: 'IfStatement'
+ consequent:
+ type: 'DoWhileStatement'
+ body:
+ type: 'IfStatement'
+ consequent: EMPTY
+ alternate: EMPTY
+ )).to.be.false
diff --git a/test/code.coffee b/test/code.coffee
new file mode 100644
index 0000000..a626eab
--- /dev/null
+++ b/test/code.coffee
@@ -0,0 +1,183 @@
+# Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+
+'use strict'
+
+expect = require('chai').expect
+esutils = require '../'
+
+describe 'code', ->
+ describe 'isDecimalDigit', ->
+ it 'returns true if provided code is decimal digit', ->
+ for ch in [0..9]
+ expect(esutils.code.isDecimalDigit((ch + '').charCodeAt(0))).to.be.true
+
+ it 'returns false if provided code is not decimal digit', ->
+ for code in ['a'.charCodeAt(0)..'z'.charCodeAt(0)]
+ expect(esutils.code.isDecimalDigit(code)).to.be.false
+
+ for code in ['A'.charCodeAt(0)..'Z'.charCodeAt(0)]
+ expect(esutils.code.isDecimalDigit(code)).to.be.false
+
+ describe 'isHexDigit', ->
+ it 'returns true if provided code is hexadecimal digit', ->
+ for ch in [0..9]
+ expect(esutils.code.isHexDigit((ch + '').charCodeAt(0))).to.be.true
+
+ for code in ['a'.charCodeAt(0)..'f'.charCodeAt(0)]
+ expect(esutils.code.isHexDigit(code)).to.be.true
+
+ for code in ['A'.charCodeAt(0)..'F'.charCodeAt(0)]
+ expect(esutils.code.isHexDigit(code)).to.be.true
+
+ it 'returns false if provided code is not hexadecimal digit', ->
+ for code in ['g'.charCodeAt(0)..'z'.charCodeAt(0)]
+ expect(esutils.code.isHexDigit(code)).to.be.false
+
+ for code in ['G'.charCodeAt(0)..'Z'.charCodeAt(0)]
+ expect(esutils.code.isHexDigit(code)).to.be.false
+
+ describe 'isOctalDigit', ->
+ it 'returns true if provided code is octal digit', ->
+ for ch in [0..7]
+ expect(esutils.code.isOctalDigit((ch + '').charCodeAt(0))).to.be.true
+
+ it 'returns false if provided code is not octal digit', ->
+ for ch in [8..9]
+ expect(esutils.code.isOctalDigit((ch + '').charCodeAt(0))).to.be.false
+
+ for code in ['a'.charCodeAt(0)..'z'.charCodeAt(0)]
+ expect(esutils.code.isOctalDigit(code)).to.be.false
+
+ for code in ['A'.charCodeAt(0)..'Z'.charCodeAt(0)]
+ expect(esutils.code.isOctalDigit(code)).to.be.false
+
+ describe 'isWhiteSpace', ->
+ it 'returns true if provided code is white space', ->
+ codes = [
+ 0x0009 # TAB
+ 0x000B # VT
+ 0x000C # FF
+ 0x0020 # SP
+ 0x00A0 # NBSP
+ 0xFEFF # BOM
+
+ # Zs
+ 0x1680
+ 0x180E
+ 0x2000
+ 0x2001
+ 0x2002
+ 0x2003
+ 0x2004
+ 0x2005
+ 0x2006
+ 0x2007
+ 0x2008
+ 0x2009
+ 0x200A
+ 0x202F
+ 0x205F
+ 0x3000
+ ]
+ for code in codes
+ expect(esutils.code.isWhiteSpace(code)).to.be.true
+
+ it 'returns false if provided code is not white space', ->
+ for ch in [0..9]
+ expect(esutils.code.isWhiteSpace((ch + '').charCodeAt(0))).to.be.false
+
+ for code in ['a'.charCodeAt(0)..'z'.charCodeAt(0)]
+ expect(esutils.code.isWhiteSpace(code)).to.be.false
+
+ for code in ['A'.charCodeAt(0)..'Z'.charCodeAt(0)]
+ expect(esutils.code.isWhiteSpace(code)).to.be.false
+
+ describe 'isLineTerminator', ->
+ it 'returns true if provided code is line terminator', ->
+ codes = [
+ 0x000A
+ 0x000D
+ 0x2028
+ 0x2029
+ ]
+ for code in codes
+ expect(esutils.code.isLineTerminator(code)).to.be.true
+
+ it 'returns false if provided code is not line terminator', ->
+ for ch in [0..9]
+ expect(esutils.code.isLineTerminator((ch + '').charCodeAt(0))).to.be.false
+
+ for code in ['a'.charCodeAt(0)..'z'.charCodeAt(0)]
+ expect(esutils.code.isLineTerminator(code)).to.be.false
+
+ for code in ['A'.charCodeAt(0)..'Z'.charCodeAt(0)]
+ expect(esutils.code.isLineTerminator(code)).to.be.false
+
+ describe 'isIdentifierStartES5', ->
+ it 'returns true if provided code can be a start of Identifier in ES5', ->
+ characters = ['a', '_', '$', 'ゆ']
+ for code in characters.map((ch) -> ch.charCodeAt(0))
+ expect(esutils.code.isIdentifierStartES5(code)).to.be.true
+
+ it 'returns false if provided code cannot be a start of Identifier in ES5', ->
+ for ch in [0..9]
+ expect(esutils.code.isIdentifierStartES5((ch + '').charCodeAt(0))).to.be.false
+
+ describe 'isIdentifierPartES5', ->
+ it 'returns true if provided code can be a part of Identifier in ES5', ->
+ characters = ['a', '_', '$', 'ゆ']
+ for code in characters.map((ch) -> ch.charCodeAt(0))
+ expect(esutils.code.isIdentifierPartES5(code)).to.be.true
+
+ for ch in [0..9]
+ expect(esutils.code.isIdentifierPartES5((ch + '').charCodeAt(0))).to.be.true
+
+ it 'returns false if provided code cannot be a part of Identifier in ES5', ->
+ expect(esutils.code.isIdentifierPartES5('+'.charCodeAt(0))).to.be.false
+ expect(esutils.code.isIdentifierPartES5('-'.charCodeAt(0))).to.be.false
+
+ describe 'isIdentifierStartES6', ->
+ it 'returns true if provided code can be a start of Identifier in ES6', ->
+ characters = ['a', '_', '$', 'ゆ']
+ for code in characters.map((ch) -> ch.charCodeAt(0))
+ expect(esutils.code.isIdentifierStartES6(code)).to.be.true
+
+ it 'returns false if provided code cannot be a start of Identifier in ES6', ->
+ for ch in [0..9]
+ expect(esutils.code.isIdentifierStartES6((ch + '').charCodeAt(0))).to.be.false
+
+ describe 'isIdentifierPartES6', ->
+ it 'returns true if provided code can be a part of Identifier in ES6', ->
+ characters = ['a', '_', '$', 'ゆ']
+ for code in characters.map((ch) -> ch.charCodeAt(0))
+ expect(esutils.code.isIdentifierPartES6(code)).to.be.true
+
+ for ch in [0..9]
+ expect(esutils.code.isIdentifierPartES6((ch + '').charCodeAt(0))).to.be.true
+
+ it 'supports astral symbols', ->
+ expect(esutils.code.isIdentifierPartES6(0xE01D5)).to.be.true
+
+ it 'returns false if provided code cannot be a part of Identifier in ES6', ->
+ expect(esutils.code.isIdentifierPartES6('+'.charCodeAt(0))).to.be.false
+ expect(esutils.code.isIdentifierPartES6('-'.charCodeAt(0))).to.be.false
diff --git a/test/keyword.coffee b/test/keyword.coffee
new file mode 100644
index 0000000..9fef055
--- /dev/null
+++ b/test/keyword.coffee
@@ -0,0 +1,400 @@
+# Copyright (C) 2013 Yusuke Suzuki <utatane.tea at 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.
+
+'use strict'
+
+expect = require('chai').expect
+esutils = require '../'
+
+KW = [
+ 'if'
+ 'in'
+ 'do'
+ 'var'
+ 'for'
+ 'new'
+ 'try'
+ 'this'
+ 'else'
+ 'case'
+ 'void'
+ 'with'
+ 'enum'
+ 'while'
+ 'break'
+ 'catch'
+ 'throw'
+ 'const'
+ 'class'
+ 'super'
+ 'return'
+ 'typeof'
+ 'delete'
+ 'switch'
+ 'export'
+ 'import'
+ 'default'
+ 'finally'
+ 'extends'
+ 'function'
+ 'continue'
+ 'debugger'
+ 'instanceof'
+]
+
+SRW = [
+ 'implements'
+ 'interface'
+ 'package'
+ 'private'
+ 'protected'
+ 'public'
+ 'static'
+ 'let'
+]
+
+describe 'keyword', ->
+ describe 'isKeywordES6', ->
+ it 'returns true if provided string is keyword under non-strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isKeywordES6(word, no)).to.be.true
+
+ expect(esutils.keyword.isKeywordES6('yield', no)).to.be.true
+
+ it 'returns false if provided string is not keyword under non-strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isKeywordES6(word, no)).to.be.false
+
+ for word in SRW
+ expect(esutils.keyword.isKeywordES6(word, no)).to.be.false
+
+ it 'returns true if provided string is keyword under strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isKeywordES6(word, yes)).to.be.true
+
+ expect(esutils.keyword.isKeywordES6('yield', yes)).to.be.true
+
+ for word in SRW
+ expect(esutils.keyword.isKeywordES6(word, yes)).to.be.true
+
+
+ it 'returns false if provided string is not keyword under strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isKeywordES6(word, yes)).to.be.false
+
+
+ describe 'isKeywordES5', ->
+ it 'returns true if provided string is keyword under non-strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isKeywordES5(word, no)).to.be.true
+
+ it 'returns false if provided string is not keyword under non-strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isKeywordES5(word, no)).to.be.false
+
+ for word in SRW
+ expect(esutils.keyword.isKeywordES5(word, no)).to.be.false
+
+ expect(esutils.keyword.isKeywordES5('yield', no)).to.be.false
+
+ it 'returns true if provided string is keyword under strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isKeywordES5(word, yes)).to.be.true
+
+ expect(esutils.keyword.isKeywordES5('yield', yes)).to.be.true
+
+ for word in SRW
+ expect(esutils.keyword.isKeywordES5(word, yes)).to.be.true
+
+
+ it 'returns false if provided string is not keyword under strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isKeywordES5(word, yes)).to.be.false
+
+
+ describe 'isReservedWordES6', ->
+ it 'returns true for null/boolean values', ->
+ expect(esutils.keyword.isReservedWordES6('null', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES6('null', yes)).to.be.true
+ expect(esutils.keyword.isReservedWordES6('true', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES6('true', yes)).to.be.true
+ expect(esutils.keyword.isReservedWordES6('false', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES6('false', yes)).to.be.true
+
+ # isReservedWordES6 has the same properties as isKeywordES6
+
+ it 'returns true if provided string is keyword under non-strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isReservedWordES6(word, no)).to.be.true
+
+ expect(esutils.keyword.isReservedWordES6('yield', no)).to.be.true
+
+ it 'returns false if provided string is not keyword under non-strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isReservedWordES6(word, no)).to.be.false
+
+ for word in SRW
+ expect(esutils.keyword.isReservedWordES6(word, no)).to.be.false
+
+ it 'returns true if provided string is keyword under strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isReservedWordES6(word, yes)).to.be.true
+
+ expect(esutils.keyword.isReservedWordES6('yield', yes)).to.be.true
+
+ for word in SRW
+ expect(esutils.keyword.isReservedWordES6(word, yes)).to.be.true
+
+
+ it 'returns false if provided string is not keyword under strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isReservedWordES6(word, yes)).to.be.false
+
+
+ describe 'isReservedWordES5', ->
+ it 'returns true for null/boolean values', ->
+ expect(esutils.keyword.isReservedWordES5('null', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES5('null', yes)).to.be.true
+ expect(esutils.keyword.isReservedWordES5('true', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES5('true', yes)).to.be.true
+ expect(esutils.keyword.isReservedWordES5('false', no)).to.be.true
+ expect(esutils.keyword.isReservedWordES5('false', yes)).to.be.true
+
+ # isReservedWordES5 has the same properties as isKeywordES5
+
+ it 'returns true if provided string is keyword under non-strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isReservedWordES5(word, no)).to.be.true
+
+ it 'returns false if provided string is not keyword under non-strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isReservedWordES5(word, no)).to.be.false
+
+ for word in SRW
+ expect(esutils.keyword.isReservedWordES5(word, no)).to.be.false
+
+ expect(esutils.keyword.isReservedWordES5('yield', no)).to.be.false
+
+ it 'returns true if provided string is keyword under strict mode', ->
+ for word in KW
+ expect(esutils.keyword.isReservedWordES5(word, yes)).to.be.true
+
+ expect(esutils.keyword.isReservedWordES5('yield', yes)).to.be.true
+
+ for word in SRW
+ expect(esutils.keyword.isReservedWordES5(word, yes)).to.be.true
+
+
+ it 'returns false if provided string is not keyword under strict mode', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isReservedWordES5(word, yes)).to.be.false
+
+
+ describe 'isRestrictedWord', ->
+ it 'returns true if provided string is "eval" or "arguments"', ->
+ expect(esutils.keyword.isRestrictedWord('eval')).to.be.true
+ expect(esutils.keyword.isRestrictedWord('arguments')).to.be.true
+
+ it 'returns false if provided string is not "eval" or "arguments"', ->
+ words = [
+ 'hello'
+ '20'
+ '$'
+ 'ゆゆ式'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isRestrictedWord(word)).to.be.false
+
+
+ describe 'isIdentifierName', ->
+ it 'returns false if provided string is empty', ->
+ expect(esutils.keyword.isIdentifierNameES5('')).to.be.false
+ expect(esutils.keyword.isIdentifierNameES6('')).to.be.false
+
+ it 'returns true if provided string is IdentifierName', ->
+ words = [
+ 'hello'
+ '$'
+ 'ゆゆ式'
+ '$20'
+ 'hello20'
+ '_'
+ 'if'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierNameES5(word)).to.be.true
+ expect(esutils.keyword.isIdentifierNameES6(word)).to.be.true
+
+
+ it 'returns false if provided string is not IdentifierName', ->
+ words = [
+ '+hello'
+ '0$'
+ '-ゆゆ式'
+ '#_'
+ '_#'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierNameES5(word)).to.be.false
+ expect(esutils.keyword.isIdentifierNameES6(word)).to.be.false
+
+ it 'supports astral symbols', ->
+ expect(esutils.keyword.isIdentifierNameES6('x\uDB40\uDDD5')).to.be.true
+
+
+ describe 'isIdentifierES5', ->
+ it 'returns false if provided string is empty', ->
+ expect(esutils.keyword.isIdentifierES5('')).to.be.false
+
+ it 'returns true if provided string is Identifier', ->
+ words = [
+ 'hello'
+ '$'
+ 'ゆゆ式'
+ '$20'
+ 'hello20'
+ '_'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierES5(word)).to.be.true
+
+ expect(esutils.keyword.isIdentifierES5('yield', no)).to.be.true
+ expect(esutils.keyword.isIdentifierES5('let', no)).to.be.true
+
+ it 'returns false if provided string is not Identifier', ->
+ words = [
+ '+hello'
+ '0$'
+ '-ゆゆ式'
+ '#_'
+ '_#'
+ 'if'
+ 'null'
+ 'true'
+ 'false'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierES5(word)).to.be.false
+
+ expect(esutils.keyword.isIdentifierES5('yield', yes)).to.be.false
+ expect(esutils.keyword.isIdentifierES5('let', yes)).to.be.false
+
+
+ describe 'isIdentifierES6', ->
+ it 'returns false if provided string is empty', ->
+ expect(esutils.keyword.isIdentifierES6('')).to.be.false
+
+ it 'returns true if provided string is Identifier', ->
+ words = [
+ 'hello'
+ '$'
+ 'ゆゆ式'
+ '$20'
+ 'hello20'
+ '_'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierES6(word)).to.be.true
+
+ expect(esutils.keyword.isIdentifierES6('let', no)).to.be.true
+
+ it 'returns false if provided string is not Identifier', ->
+ words = [
+ '+hello'
+ '0$'
+ '-ゆゆ式'
+ '#_'
+ '_#'
+ 'if'
+ 'null'
+ 'true'
+ 'false'
+ ]
+
+ for word in words
+ expect(esutils.keyword.isIdentifierES6(word)).to.be.false
+
+ expect(esutils.keyword.isIdentifierES6('yield', no)).to.be.false
+ expect(esutils.keyword.isIdentifierES6('yield', yes)).to.be.false
+ expect(esutils.keyword.isIdentifierES6('let', yes)).to.be.false
diff --git a/tools/generate-identifier-regex.js b/tools/generate-identifier-regex.js
new file mode 100644
index 0000000..01c8153
--- /dev/null
+++ b/tools/generate-identifier-regex.js
@@ -0,0 +1,87 @@
+// Based on https://gist.github.com/mathiasbynens/6334847 by @mathias
+'use strict';
+
+var regenerate = require('regenerate');
+
+// Which Unicode version should be used?
+var version = '7.0.0';
+
+// Set up a shorthand function to import Unicode data.
+var get = function(what) {
+ return require('unicode-' + version + '/' + what + '/code-points');
+};
+
+// Get the Unicode categories needed to construct the ES5 regex.
+var Lu = get('categories/Lu');
+var Ll = get('categories/Ll');
+var Lt = get('categories/Lt');
+var Lm = get('categories/Lm');
+var Lo = get('categories/Lo');
+var Nl = get('categories/Nl');
+var Mn = get('categories/Mn');
+var Mc = get('categories/Mc');
+var Nd = get('categories/Nd');
+var Pc = get('categories/Pc');
+
+var es5regexes = (function() { // ES 5.1
+ // http://mathiasbynens.be/notes/javascript-identifiers#valid-identifier-names
+ var identifierStart = regenerate()
+ .add(Lu, Ll, Lt, Lm, Lo, Nl)
+ .removeRange(0x010000, 0x10FFFF) // remove astral symbols
+ .removeRange(0x0, 0x7F); // remove ASCII symbols (esutils-specific)
+ var identifierStartCodePoints = identifierStart.toArray();
+ var identifierPart = regenerate(identifierStartCodePoints)
+ .add('\u200C', '\u200D', Mn, Mc, Nd, Pc)
+ .removeRange(0x010000, 0x10FFFF) // remove astral symbols
+ .removeRange(0x0, 0x7F); // remove ASCII symbols (esutils-specific)
+ return {
+ 'NonAsciiIdentifierStart': '/' + identifierStart + '/',
+ 'NonAsciiIdentifierPart': '/' + identifierPart + '/',
+ };
+}());
+
+// Get the Unicode properties needed to construct the ES6 regex.
+var ID_Start = get('properties/ID_Start');
+var ID_Continue = get('properties/ID_Continue');
+var Other_ID_Start = get('properties/Other_ID_Start');
+
+var es6regexes = (function() {
+ // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifier-names-static-semantics-early-errors
+ // http://unicode.org/reports/tr31/#Default_Identifier_Syntax
+ // https://bugs.ecmascript.org/show_bug.cgi?id=2717#c0
+ var identifierStart = regenerate(ID_Start)
+ // Note: this already includes `Other_ID_Start`. http://git.io/wRCAfQ
+ .removeRange(0x0, 0x7F); // remove ASCII symbols (esutils-specific)
+ var identifierPart = regenerate(ID_Continue)
+ // Note: `ID_Continue` already includes `Other_ID_Continue`. http://git.io/wRCAfQ
+ .add(Other_ID_Start)
+ .add('\u200C', '\u200D')
+ .removeRange(0x0, 0x7F); // remove ASCII symbols (esutils-specific)
+
+ return {
+ 'NonAsciiIdentifierStart': '/' + identifierStart + '/',
+ 'NonAsciiIdentifierPart': '/' + identifierPart + '/',
+ };
+}());
+
+console.log(
+ '// ECMAScript 5.1/Unicode v%s NonAsciiIdentifierStart:\n%s\n',
+ version,
+ es5regexes.NonAsciiIdentifierStart
+);
+console.log(
+ '// ECMAScript 5.1/Unicode v%s NonAsciiIdentifierPart:\n%s\n',
+ version,
+ es5regexes.NonAsciiIdentifierPart
+);
+
+console.log(
+ '// ECMAScript 6/Unicode v%s NonAsciiIdentifierStart:\n%s\n',
+ version,
+ es6regexes.NonAsciiIdentifierStart
+);
+console.log(
+ '// ECMAScript 6/Unicode v%s NonAsciiIdentifierPart:\n%s',
+ version,
+ es6regexes.NonAsciiIdentifierPart
+);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-esutils.git
More information about the Pkg-javascript-commits
mailing list