[Pkg-javascript-commits] [node-jsesc] 01/05: Imported Upstream version 2.1.0

Julien Puydt julien.puydt at laposte.net
Tue May 31 16:13:00 UTC 2016


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-jsesc.

commit 94af1810785dd8627d48d1ca06e47da6b7efbcc6
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Tue May 31 18:07:58 2016 +0200

    Imported Upstream version 2.1.0
---
 .editorconfig  |   12 +
 .travis.yml    |   19 +-
 Gruntfile.js   |   55 +--
 README.md      |  117 ++++---
 bower.json     |   17 -
 component.json |   17 -
 jsesc.js       |  519 ++++++++++++++---------------
 package.json   |   91 ++---
 src/data.js    |    8 +-
 src/jsesc.js   |  519 ++++++++++++++---------------
 tests/tests.js | 1011 ++++++++++++++++----------------------------------------
 11 files changed, 936 insertions(+), 1449 deletions(-)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..dbd9e6b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = tab
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{README.md,package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/.travis.yml b/.travis.yml
index 3423994..332433c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,7 @@
 language: node_js
 node_js:
+  - "4"
+  - "5"
   - "6"
-before_script:
-  - "npm install -g grunt-cli"
-  # Narwhal uses a hardcoded path to openjdk v6, so use that version
-  - "sudo apt-get update -qq"
-  - "sudo apt-get install -qq openjdk-6-jre"
-  - "PACKAGE=rhino1_7R5; wget https://github.com/mozilla/rhino/releases/download/Rhino1_7R5_RELEASE/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
-  - "PACKAGE=rhino1_7R5; echo -e '#!/bin/sh\\njava -jar /opt/'$PACKAGE'/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino"
-  - "PACKAGE=ringojs-0.11; wget https://github.com/ringo/ringojs/releases/download/v0.11.0/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
-  - "PACKAGE=ringojs-0.11; sudo ln -s /opt/$PACKAGE/bin/ringo /usr/local/bin/ringo && sudo chmod +x /usr/local/bin/ringo"
-  - "PACKAGE=v0.3.2; wget https://github.com/280north/narwhal/archive/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
-  - "PACKAGE=narwhal-0.3.2; sudo ln -s /opt/$PACKAGE/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal"
-  # If the enviroment stores rt.jar in a different directory, find it and symlink the directory
-  - "PREFIX=/usr/lib/jvm; if [ ! -d $PREFIX/java-6-openjdk ]; then for d in $PREFIX/java-6-openjdk-*; do if [ -e $d/jre/lib/rt.jar ]; then sudo ln -s $d $PREFIX/java-6-openjdk; break; fi; done; fi"
-script:
-  - "grunt ci"
 after_script:
-  - "grunt shell:cover-coveralls"
+  - "npm run coveralls"
diff --git a/Gruntfile.js b/Gruntfile.js
index d9a8cb0..3a6a3ff 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,46 +1,10 @@
 module.exports = function(grunt) {
 
 	grunt.initConfig({
-		'shell': {
-			'options': {
-				'stdout': true,
-				'stderr': true,
-				'failOnError': true
-			},
-			'cover-html': {
-				'command': 'istanbul cover --report "html" --verbose --dir "coverage" "tests/tests.js"'
-			},
-			'cover-coveralls': {
-				'command': 'istanbul cover --verbose --dir "coverage" "tests/tests.js" && coveralls < coverage/lcov.info; rm -rf coverage/lcov*'
-			},
-			'test-narwhal': {
-				'command': 'echo "Testing in Narwhal..."; export NARWHAL_OPTIMIZATION=-1; narwhal "tests/tests.js"'
-			},
-			'test-phantomjs': {
-				'command': 'echo "Testing in PhantomJS..."; phantomjs "tests/tests.js"'
-			},
-			'test-rhino': {
-				'command': 'echo "Testing in Rhino..."; rhino -opt -1 "tests.js"',
-				'options': {
-					'execOptions': {
-						'cwd': 'tests'
-					}
-				}
-			},
-			'test-ringo': {
-				'command': 'echo "Testing in Ringo..."; ringo -o -1 "tests/tests.js"'
-			},
-			'test-node': {
-				'command': 'echo "Testing in Node..."; node "tests/tests.js"'
-			},
-			'test-browser': {
-				'command': 'echo "Testing in a browser..."; open "tests/index.html"'
-			}
-		},
 		'template': {
 			'build': {
 				'options': {
-					// Generate the regular expressions dynamically using Regenerate
+					// Generate the regular expressions dynamically using Regenerate.
 					'data': require('./src/data.js')
 				},
 				'files': {
@@ -50,25 +14,10 @@ module.exports = function(grunt) {
 		}
 	});
 
-	grunt.loadNpmTasks('grunt-shell');
 	grunt.loadNpmTasks('grunt-template');
 
-	grunt.registerTask('cover', 'shell:cover-html');
-	grunt.registerTask('ci', [
-		'shell:test-narwhal',
-		'shell:test-phantomjs',
-		'shell:test-rhino',
-		'shell:test-ringo',
-		'shell:test-node'
-	]);
-	grunt.registerTask('test', [
-		'ci',
-		'shell:test-browser'
-	]);
-
 	grunt.registerTask('default', [
-		'template',
-		'shell:test-node'
+		'template'
 	]);
 
 };
diff --git a/README.md b/README.md
index d9c8f59..7f0057a 100644
--- a/README.md
+++ b/README.md
@@ -8,62 +8,16 @@ Feel free to fork if you see possible improvements!
 
 ## Installation
 
-Via [Bower](http://bower.io/):
-
-```bash
-bower install jsesc
-```
-
-Via [Component](https://github.com/component/component):
-
-```bash
-component install mathiasbynens/jsesc
-```
-
 Via [npm](https://www.npmjs.com/):
 
 ```bash
 npm install jsesc
 ```
 
-In a browser:
-
-```html
-<script src="jsesc.js"></script>
-```
-
-In [Node.js](https://nodejs.org/) and [RingoJS](http://ringojs.org/):
-
-```js
-var jsesc = require('jsesc');
-```
-
-In [Narwhal](http://narwhaljs.org/):
+In [Node.js](https://nodejs.org/):
 
 ```js
-var jsesc = require('jsesc').jsesc;
-```
-
-In [Rhino](http://www.mozilla.org/rhino/):
-
-```js
-load('jsesc.js');
-```
-
-Using an AMD loader like [RequireJS](http://requirejs.org/):
-
-```js
-require(
-  {
-    'paths': {
-      'jsesc': 'path/to/jsesc'
-    }
-  },
-  ['jsesc'],
-  function(jsesc) {
-    console.log(jsesc);
-  }
-);
+const jsesc = require('jsesc');
 ```
 
 ## API
@@ -137,6 +91,32 @@ jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
 // → '["Ich \\u2665 B\\xFCcher","foo \\uD834\\uDF06 bar"]'
 ```
 
+#### `numbers`
+
+The default value for the `numbers` option is `'decimal'`. This means that any numeric values will be represented using decimal integer literals. Other valid options are `binary`, `octal`, and `hexadecimal`, which result in binary integer literals, octal integer literals, and hexadecimal integer literals, respectively.
+
+```js
+jsesc(42, {
+  'numbers': 'binary'
+});
+// → '0b101010'
+
+jsesc(42, {
+  'numbers': 'octal'
+});
+// → '0o52'
+
+jsesc(42, {
+  'numbers': 'decimal'
+});
+// → '42'
+
+jsesc(42, {
+  'numbers': 'hexadecimal'
+});
+// → '0x2A'
+```
+
 #### `wrap`
 
 The `wrap` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output will be a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified through the `quotes` setting.
@@ -266,6 +246,24 @@ jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
 
 This setting has no effect on the output for strings.
 
+#### `indentLevel`
+
+The `indentLevel` option takes a numeric value, and defaults to `0`. It represents the current indentation level, i.e. the number of times the value of [the `indent` option](#indent) is repeated.
+
+```js
+jsesc(['a', 'b', 'c'], {
+  'compact': false,
+  'indentLevel': 1
+});
+// → '[\n\t\t\'a\',\n\t\t\'b\',\n\t\t\'c\'\n\t]'
+
+jsesc(['a', 'b', 'c'], {
+  'compact': false,
+  'indentLevel': 2
+});
+// → '[\n\t\t\t\'a\',\n\t\t\t\'b\',\n\t\t\t\'c\'\n\t\t]'
+```
+
 #### `json`
 
 The `json` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output is valid JSON. [Hexadecimal character escape sequences](https://mathiasbynens.be/notes/javascript-escapes#hexadecimal) and [the `\v` or `\0` escape sequences](https://mathiasbynens.be/notes/javascript-escapes#single) will not be used. Setting `json: true` implies `quotes: 'double', wrap: true, es6: false`, although these values can still be overridden if needed — but  [...]
@@ -303,14 +301,21 @@ jsesc([ undefined, -Infinity ], {
 
 #### `lowercaseHex`
 
-The `lowercaseHex` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the alphabetical hexadecimal digits in escape sequences in the output are in lowercase.
+The `lowercaseHex` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, any alphabetical hexadecimal digits in escape sequences as well as any hexadecimal integer literals (see [the `numbers` option](#numbers)) in the output are in lowercase.
 
 ```js
 jsesc('Ich ♥ Bücher', {
-  'lowercaseHex': true,
+  'lowercaseHex': true
 });
 // → 'Ich \\u2665 B\\xfccher'
 //                    ^^
+
+jsesc(42, {
+  'numbers': 'hexadecimal',
+  'lowercaseHex': true
+});
+// → '0x2a'
+//      ^^
 ```
 
 ### `jsesc.version`
@@ -375,17 +380,9 @@ See `jsesc --help` for the full list of options.
 
 ## Support
 
-This library has been tested in at least Chrome 27, Firefox 3, Safari 4, Opera 10, IE 6, Node.js v6.0.0, Narwhal 0.3.2, RingoJS 0.8-0.11, PhantomJS 1.9.0, and Rhino 1.7RC4.
-
-**Note:** Using the `json` option on objects or arrays that contain non-string values relies on `JSON.parse()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](https://bestiejs.github.io/json3/).
-
-## Unit tests & code coverage
-
-After cloning this repository, run `npm install` to install the dependencies needed for development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
-
-Once that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use `grunt test`.
+As of v2.0.0, jsesc supports Node.js v4+ only.
 
-To generate the code coverage report, use `grunt cover`.
+Older versions (up to jsesc v1.3.0) support Chrome 27, Firefox 3, Safari 4, Opera 10, IE 6, Node.js v6.0.0, Narwhal 0.3.2, RingoJS 0.8-0.11, PhantomJS 1.9.0, and Rhino 1.7RC4. **Note:** Using the `json` option on objects or arrays that contain non-string values relies on `JSON.parse()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](https://bestiejs.github.io/json3/).
 
 ## Author
 
diff --git a/bower.json b/bower.json
deleted file mode 100644
index f2ad633..0000000
--- a/bower.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-	"name": "jsesc",
-	"version": "1.2.0",
-	"main": "jsesc.js",
-	"ignore": [
-		"bin",
-		"coverage",
-		"man",
-		"src",
-		"tests",
-		".*",
-		"component.json",
-		"Gruntfile.js",
-		"node_modules",
-		"package.json"
-	]
-}
diff --git a/component.json b/component.json
deleted file mode 100644
index 09591b8..0000000
--- a/component.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-	"name": "jsesc",
-	"version": "1.2.0",
-	"description": "A JavaScript library for escaping JavaScript strings while generating the shortest possible ASCII-only output.",
-	"repo": "mathiasbynens/jsesc",
-	"license": "MIT",
-	"scripts": [
-		"jsesc.js"
-	],
-	"main": "jsesc.js",
-	"keywords": [
-		"string",
-		"escape",
-		"javascript",
-		"tool"
-	]
-}
diff --git a/jsesc.js b/jsesc.js
index 8827ce3..13988de 100644
--- a/jsesc.js
+++ b/jsesc.js
@@ -1,296 +1,299 @@
-/*! https://mths.be/jsesc v1.2.0 by @mathias */
-;(function(root) {
+'use strict';
 
-	// Detect free variables `exports`
-	var freeExports = typeof exports == 'object' && exports;
+const object = {};
+const hasOwnProperty = object.hasOwnProperty;
+const forOwn = function(object, callback) {
+	for (const key in object) {
+		if (hasOwnProperty.call(object, key)) {
+			callback(key, object[key]);
+		}
+	}
+};
 
-	// Detect free variable `module`
-	var freeModule = typeof module == 'object' && module &&
-		module.exports == freeExports && module;
+const extend = function(destination, source) {
+	if (!source) {
+		return destination;
+	}
+	forOwn(source, function(key, value) {
+		destination[key] = value;
+	});
+	return destination;
+};
 
-	// Detect free variable `global`, from Node.js or Browserified code,
-	// and use it as `root`
-	var freeGlobal = typeof global == 'object' && global;
-	if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
-		root = freeGlobal;
+const forEach = function(array, callback) {
+	const length = array.length;
+	let index = -1;
+	while (++index < length) {
+		callback(array[index]);
 	}
+};
 
-	/*--------------------------------------------------------------------------*/
+const toString = object.toString;
+const isArray = Array.isArray;
+const isObject = function(value) {
+	// This is a very simple check, but it’s good enough for what we need.
+	return toString.call(value) == '[object Object]';
+};
+const isString = function(value) {
+	return typeof value == 'string' ||
+		toString.call(value) == '[object String]';
+};
+const isNumber = function(value) {
+	return typeof value == 'number' ||
+		toString.call(value) == '[object Number]';
+};
+const isFunction = function(value) {
+	return typeof value == 'function';
+};
+const isMap = function(value) {
+	return toString.call(value) == '[object Map]';
+};
+const isSet = function(value) {
+	return toString.call(value) == '[object Set]';
+};
 
-	var object = {};
-	var hasOwnProperty = object.hasOwnProperty;
-	var forOwn = function(object, callback) {
-		var key;
-		for (key in object) {
-			if (hasOwnProperty.call(object, key)) {
-				callback(key, object[key]);
-			}
-		}
-	};
+/*--------------------------------------------------------------------------*/
 
-	var extend = function(destination, source) {
-		if (!source) {
-			return destination;
-		}
-		forOwn(source, function(key, value) {
-			destination[key] = value;
-		});
-		return destination;
-	};
+// https://mathiasbynens.be/notes/javascript-escapes#single
+const singleEscapes = {
+	'"': '\\"',
+	'\'': '\\\'',
+	'\\': '\\\\',
+	'\b': '\\b',
+	'\f': '\\f',
+	'\n': '\\n',
+	'\r': '\\r',
+	'\t': '\\t'
+	// `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
+	// '\v': '\\x0B'
+};
+const regexSingleEscape = /["'\\\b\f\n\r\t]/;
 
-	var forEach = function(array, callback) {
-		var length = array.length;
-		var index = -1;
-		while (++index < length) {
-			callback(array[index]);
-		}
-	};
+const regexDigit = /[0-9]/;
+const regexWhitelist = /[ !#-&\(-\[\]-~]/;
 
-	var toString = object.toString;
-	var isArray = function(value) {
-		return toString.call(value) == '[object Array]';
-	};
-	var isObject = function(value) {
-		// This is a very simple check, but it’s good enough for what we need.
-		return toString.call(value) == '[object Object]';
-	};
-	var isString = function(value) {
-		return typeof value == 'string' ||
-			toString.call(value) == '[object String]';
-	};
-	var isFunction = function(value) {
-		// In a perfect world, the `typeof` check would be sufficient. However,
-		// in Chrome 1–12, `typeof /x/ == 'object'`, and in IE 6–8
-		// `typeof alert == 'object'` and similar for other host objects.
-		return typeof value == 'function' ||
-			toString.call(value) == '[object Function]';
+const jsesc = function(argument, options) {
+	const increaseIndentation = function() {
+		oldIndent = indent;
+		++options.indentLevel;
+		indent = options.indent.repeat(options.indentLevel)
 	};
-	var isMap = function(value) {
-		return toString.call(value) == '[object Map]';
+	// Handle options
+	const defaults = {
+		'escapeEverything': false,
+		'escapeEtago': false,
+		'quotes': 'single',
+		'wrap': false,
+		'es6': false,
+		'json': false,
+		'compact': true,
+		'lowercaseHex': false,
+		'numbers': 'decimal',
+		'indent': '\t',
+		'indentLevel': 0,
+		'__inline1__': false,
+		'__inline2__': false
 	};
-	var isSet = function(value) {
-		return toString.call(value) == '[object Set]';
-	};
-
-	/*--------------------------------------------------------------------------*/
-
-	// https://mathiasbynens.be/notes/javascript-escapes#single
-	var singleEscapes = {
-		'"': '\\"',
-		'\'': '\\\'',
-		'\\': '\\\\',
-		'\b': '\\b',
-		'\f': '\\f',
-		'\n': '\\n',
-		'\r': '\\r',
-		'\t': '\\t'
-		// `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
-		// '\v': '\\x0B'
-	};
-	var regexSingleEscape = /["'\\\b\f\n\r\t]/;
+	const json = options && options.json;
+	if (json) {
+		defaults.quotes = 'double';
+		defaults.wrap = true;
+	}
+	options = extend(defaults, options);
+	if (options.quotes != 'single' && options.quotes != 'double') {
+		options.quotes = 'single';
+	}
+	const quote = options.quotes == 'double' ? '"' : '\'';
+	const compact = options.compact;
+	const lowercaseHex = options.lowercaseHex;
+	let indent = options.indent.repeat(options.indentLevel);
+	let oldIndent = '';
+	const inline1 = options.__inline1__;
+	const inline2 = options.__inline2__;
+	const newLine = compact ? '' : '\n';
+	let result;
+	let isEmpty = true;
+	const useBinNumbers = options.numbers == 'binary';
+	const useOctNumbers = options.numbers == 'octal';
+	const useDecNumbers = options.numbers == 'decimal';
+	const useHexNumbers = options.numbers == 'hexadecimal';
 
-	var regexDigit = /[0-9]/;
-	var regexWhitelist = /[ !#-&\(-\[\]-~]/;
+	if (json && argument && isFunction(argument.toJSON)) {
+		argument = argument.toJSON();
+	}
 
-	var jsesc = function(argument, options) {
-		// Handle options
-		var defaults = {
-			'escapeEverything': false,
-			'escapeEtago': false,
-			'quotes': 'single',
-			'wrap': false,
-			'es6': false,
-			'json': false,
-			'compact': true,
-			'lowercaseHex': false,
-			'indent': '\t',
-			'__indent__': ''
-		};
-		var json = options && options.json;
-		if (json) {
-			defaults.quotes = 'double';
-			defaults.wrap = true;
-		}
-		options = extend(defaults, options);
-		if (options.quotes != 'single' && options.quotes != 'double') {
-			options.quotes = 'single';
+	if (!isString(argument)) {
+		if (isMap(argument)) {
+			if (argument.size == 0) {
+				return 'new Map()';
+			}
+			if (!compact) {
+				options.__inline1__ = true;
+				options.__inline2__ = false;
+			}
+			return 'new Map(' + jsesc(Array.from(argument), options) + ')';
 		}
-		var quote = options.quotes == 'double' ? '"' : '\'';
-		var compact = options.compact;
-		var indent = options.indent;
-		var oldIndent;
-		var newLine = compact ? '' : '\n';
-		var result;
-		var isEmpty = true;
-
-		if (json && argument && isFunction(argument.toJSON)) {
-			argument = argument.toJSON();
+		if (isSet(argument)) {
+			if (argument.size == 0) {
+				return 'new Set()';
+			}
+			return 'new Set(' + jsesc(Array.from(argument), options) + ')';
 		}
-
-		if (!isString(argument)) {
-			if (isMap(argument)) {
-				if (argument.size == 0) {
-					return 'new Map()';
-				}
-				return 'new Map(' + jsesc(Array.from(argument), options) + ')';
+		if (isArray(argument)) {
+			result = [];
+			options.wrap = true;
+			if (inline1) {
+				options.__inline1__ = false;
+				options.__inline2__ = true;
 			}
-			if (isSet(argument)) {
-				if (argument.size == 0) {
-					return 'new Set()';
-				}
-				return 'new Set(' + jsesc(Array.from(argument), options) + ')';
+			if (!inline2) {
+				increaseIndentation();
 			}
-			if (isArray(argument)) {
-				result = [];
-				options.wrap = true;
-				oldIndent = options.__indent__;
-				indent += oldIndent;
-				options.__indent__ = indent;
-				forEach(argument, function(value) {
-					isEmpty = false;
-					result.push(
-						(compact ? '' : indent) +
-						jsesc(value, options)
-					);
-				});
-				if (isEmpty) {
-					return '[]';
-				}
-				return '[' + newLine + result.join(',' + newLine) + newLine +
-					(compact ? '' : oldIndent) + ']';
-			} else if (!isObject(argument)) {
-				if (json) {
-					// For some values (e.g. `undefined`, `function` objects),
-					// `JSON.stringify(value)` returns `undefined` (which isn’t valid
-					// JSON) instead of `'null'`.
-					return JSON.stringify(argument) || 'null';
+			forEach(argument, function(value) {
+				isEmpty = false;
+				if (inline2) {
+					options.__inline2__ = false;
 				}
+				result.push(
+					(compact || inline2 ? '' : indent) +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '[]';
+			}
+			if (inline2) {
+				return '[' + result.join(', ') + ']';
+			}
+			return '[' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + ']';
+		} else if (isNumber(argument)) {
+			if (json) {
+				// Some number values (e.g. `Infinity`) cannot be represented in JSON.
+				return JSON.stringify(argument);
+			}
+			if (useDecNumbers) {
 				return String(argument);
-			} else { // it’s an object
-				result = [];
-				options.wrap = true;
-				oldIndent = options.__indent__;
-				indent += oldIndent;
-				options.__indent__ = indent;
-				forOwn(argument, function(key, value) {
-					isEmpty = false;
-					result.push(
-						(compact ? '' : indent) +
-						jsesc(key, options) + ':' +
-						(compact ? '' : ' ') +
-						jsesc(value, options)
-					);
-				});
-				if (isEmpty) {
-					return '{}';
+			}
+			if (useHexNumbers) {
+				let hexadecimal = argument.toString(16);
+				if (!lowercaseHex) {
+					hexadecimal = hexadecimal.toUpperCase();
 				}
-				return '{' + newLine + result.join(',' + newLine) + newLine +
-					(compact ? '' : oldIndent) + '}';
+				return '0x' + hexadecimal;
+			}
+			if (useBinNumbers) {
+				return '0b' + argument.toString(2);
+			}
+			if (useOctNumbers) {
+				return '0o' + argument.toString(8);
+			}
+		} else if (!isObject(argument)) {
+			if (json) {
+				// For some values (e.g. `undefined`, `function` objects),
+				// `JSON.stringify(value)` returns `undefined` (which isn’t valid
+				// JSON) instead of `'null'`.
+				return JSON.stringify(argument) || 'null';
 			}
+			return String(argument);
+		} else { // it’s an object
+			result = [];
+			options.wrap = true;
+			increaseIndentation();
+			forOwn(argument, function(key, value) {
+				isEmpty = false;
+				result.push(
+					(compact ? '' : indent) +
+					jsesc(key, options) + ':' +
+					(compact ? '' : ' ') +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '{}';
+			}
+			return '{' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + '}';
 		}
+	}
 
-		var string = argument;
-		// Loop over each code unit in the string and escape it
-		var index = -1;
-		var length = string.length;
-		var first;
-		var second;
-		var codePoint;
-		result = '';
-		while (++index < length) {
-			var character = string.charAt(index);
-			if (options.es6) {
-				first = string.charCodeAt(index);
-				if ( // check if it’s the start of a surrogate pair
-					first >= 0xD800 && first <= 0xDBFF && // high surrogate
-					length > index + 1 // there is a next code unit
-				) {
-					second = string.charCodeAt(index + 1);
-					if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
-						// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
-						codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
-						var hexadecimal = codePoint.toString(16);
-						if (!options.lowercaseHex) {
-							hexadecimal = hexadecimal.toUpperCase();
-						}
-						result += '\\u{' + hexadecimal + '}';
-						index++;
-						continue;
+	const string = argument;
+	// Loop over each code unit in the string and escape it
+	let index = -1;
+	const length = string.length;
+	result = '';
+	while (++index < length) {
+		const character = string.charAt(index);
+		if (options.es6) {
+			const first = string.charCodeAt(index);
+			if ( // check if it’s the start of a surrogate pair
+				first >= 0xD800 && first <= 0xDBFF && // high surrogate
+				length > index + 1 // there is a next code unit
+			) {
+				const second = string.charCodeAt(index + 1);
+				if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
+					// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+					const codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+					let hexadecimal = codePoint.toString(16);
+					if (!lowercaseHex) {
+						hexadecimal = hexadecimal.toUpperCase();
 					}
-				}
-			}
-			if (!options.escapeEverything) {
-				if (regexWhitelist.test(character)) {
-					// It’s a printable ASCII character that is not `"`, `'` or `\`,
-					// so don’t escape it.
-					result += character;
-					continue;
-				}
-				if (character == '"') {
-					result += quote == character ? '\\"' : character;
-					continue;
-				}
-				if (character == '\'') {
-					result += quote == character ? '\\\'' : character;
+					result += '\\u{' + hexadecimal + '}';
+					++index;
 					continue;
 				}
 			}
-			if (
-				character == '\0' &&
-				!json &&
-				!regexDigit.test(string.charAt(index + 1))
-			) {
-				result += '\\0';
+		}
+		if (!options.escapeEverything) {
+			if (regexWhitelist.test(character)) {
+				// It’s a printable ASCII character that is not `"`, `'` or `\`,
+				// so don’t escape it.
+				result += character;
 				continue;
 			}
-			if (regexSingleEscape.test(character)) {
-				// no need for a `hasOwnProperty` check here
-				result += singleEscapes[character];
+			if (character == '"') {
+				result += quote == character ? '\\"' : character;
 				continue;
 			}
-			var charCode = character.charCodeAt(0);
-			var hexadecimal = charCode.toString(16);
-			if (!options.lowercaseHex) {
-				hexadecimal = hexadecimal.toUpperCase();
+			if (character == '\'') {
+				result += quote == character ? '\\\'' : character;
+				continue;
 			}
-			var longhand = hexadecimal.length > 2 || json;
-			var escaped = '\\' + (longhand ? 'u' : 'x') +
-				('0000' + hexadecimal).slice(longhand ? -4 : -2);
-			result += escaped;
+		}
+		if (
+			character == '\0' &&
+			!json &&
+			!regexDigit.test(string.charAt(index + 1))
+		) {
+			result += '\\0';
 			continue;
 		}
-		if (options.wrap) {
-			result = quote + result + quote;
+		if (regexSingleEscape.test(character)) {
+			// no need for a `hasOwnProperty` check here
+			result += singleEscapes[character];
+			continue;
 		}
-		if (options.escapeEtago) {
-			// https://mathiasbynens.be/notes/etago
-			return result.replace(/<\/(script|style)/gi, '<\\/$1');
+		const charCode = character.charCodeAt(0);
+		let hexadecimal = charCode.toString(16);
+		if (!lowercaseHex) {
+			hexadecimal = hexadecimal.toUpperCase();
 		}
-		return result;
-	};
-
-	jsesc.version = '1.2.0';
-
-	/*--------------------------------------------------------------------------*/
-
-	// Some AMD build optimizers, like r.js, check for specific condition patterns
-	// like the following:
-	if (
-		typeof define == 'function' &&
-		typeof define.amd == 'object' &&
-		define.amd
-	) {
-		define(function() {
-			return jsesc;
-		});
-	}	else if (freeExports && !freeExports.nodeType) {
-		if (freeModule) { // in Node.js or RingoJS v0.8.0+
-			freeModule.exports = jsesc;
-		} else { // in Narwhal or RingoJS v0.7.0-
-			freeExports.jsesc = jsesc;
-		}
-	} else { // in Rhino or a web browser
-		root.jsesc = jsesc;
+		const longhand = hexadecimal.length > 2 || json;
+		const escaped = '\\' + (longhand ? 'u' : 'x') +
+			('0000' + hexadecimal).slice(longhand ? -4 : -2);
+		result += escaped;
+		continue;
 	}
+	if (options.wrap) {
+		result = quote + result + quote;
+	}
+	if (options.escapeEtago) {
+		// https://mathiasbynens.be/notes/etago
+		return result.replace(/<\/(script|style)/gi, '<\\/$1');
+	}
+	return result;
+};
+
+jsesc.version = '2.1.0';
 
-}(this));
+module.exports = jsesc;
diff --git a/package.json b/package.json
index 193b82a..b37bcd5 100644
--- a/package.json
+++ b/package.json
@@ -1,46 +1,49 @@
 {
-	"name": "jsesc",
-	"version": "1.2.0",
-	"description": "A JavaScript library for escaping JavaScript strings while generating the shortest possible valid output.",
-	"homepage": "https://mths.be/jsesc",
-	"main": "jsesc.js",
-	"bin": "bin/jsesc",
-	"man": "man/jsesc.1",
-	"keywords": [
-		"string",
-		"escape",
-		"javascript",
-		"tool"
-	],
-	"license": "MIT",
-	"author": {
-		"name": "Mathias Bynens",
-		"url": "https://mathiasbynens.be/"
-	},
-	"repository": {
-		"type": "git",
-		"url": "https://github.com/mathiasbynens/jsesc.git"
-	},
-	"bugs": "https://github.com/mathiasbynens/jsesc/issues",
-	"files": [
-		"LICENSE-MIT.txt",
-		"jsesc.js",
-		"bin/",
-		"man/"
-	],
-	"scripts": {
-		"test": "node tests/tests.js",
-		"build": "grunt template"
-	},
-	"devDependencies": {
-		"coveralls": "^2.11.6",
-		"grunt": "^0.4.5",
-		"grunt-shell": "^1.1.2",
-		"grunt-template": "^0.2.3",
-		"istanbul": "^0.4.2",
-		"qunit-extras": "^1.4.5",
-		"qunitjs": "~1.11.0",
-		"regenerate": "^1.2.1",
-		"requirejs": "^2.1.22"
-	}
+  "name": "jsesc",
+  "version": "2.1.0",
+  "description": "A JavaScript library for escaping JavaScript strings while generating the shortest possible valid output.",
+  "homepage": "https://mths.be/jsesc",
+  "engines": {
+    "node": ">=4"
+  },
+  "main": "jsesc.js",
+  "bin": "bin/jsesc",
+  "man": "man/jsesc.1",
+  "keywords": [
+    "string",
+    "escape",
+    "javascript",
+    "tool"
+  ],
+  "license": "MIT",
+  "author": {
+    "name": "Mathias Bynens",
+    "url": "https://mathiasbynens.be/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/mathiasbynens/jsesc.git"
+  },
+  "bugs": "https://github.com/mathiasbynens/jsesc/issues",
+  "files": [
+    "LICENSE-MIT.txt",
+    "jsesc.js",
+    "bin/",
+    "man/"
+  ],
+  "scripts": {
+    "build": "grunt template",
+    "coveralls": "istanbul cover --verbose --dir 'coverage' 'tests/tests.js' && coveralls < coverage/lcov.info'",
+    "cover": "istanbul cover --report 'html' --verbose --dir 'coverage' 'tests/tests.js'",
+    "test": "mocha tests"
+  },
+  "devDependencies": {
+    "coveralls": "^2.11.6",
+    "grunt": "^0.4.5",
+    "grunt-template": "^0.2.3",
+    "istanbul": "^0.4.2",
+    "mocha": "*",
+    "regenerate": "^1.3.0",
+    "requirejs": "^2.1.22"
+  }
 }
diff --git a/src/data.js b/src/data.js
index 4c99c37..654cd41 100644
--- a/src/data.js
+++ b/src/data.js
@@ -1,7 +1,9 @@
-var regenerate = require('regenerate');
-var fs = require('fs');
+'use strict';
 
-var set = regenerate()
+const regenerate = require('regenerate');
+const fs = require('fs');
+
+const set = regenerate()
 	.addRange(0x20, 0x7E) // printable ASCII symbols
 	.remove('"')          // not `"`
 	.remove('\'')         // not `'`
diff --git a/src/jsesc.js b/src/jsesc.js
index 55b0518..1514eca 100644
--- a/src/jsesc.js
+++ b/src/jsesc.js
@@ -1,296 +1,299 @@
-/*! https://mths.be/jsesc v<%= version %> by @mathias */
-;(function(root) {
+'use strict';
 
-	// Detect free variables `exports`
-	var freeExports = typeof exports == 'object' && exports;
+const object = {};
+const hasOwnProperty = object.hasOwnProperty;
+const forOwn = function(object, callback) {
+	for (const key in object) {
+		if (hasOwnProperty.call(object, key)) {
+			callback(key, object[key]);
+		}
+	}
+};
 
-	// Detect free variable `module`
-	var freeModule = typeof module == 'object' && module &&
-		module.exports == freeExports && module;
+const extend = function(destination, source) {
+	if (!source) {
+		return destination;
+	}
+	forOwn(source, function(key, value) {
+		destination[key] = value;
+	});
+	return destination;
+};
 
-	// Detect free variable `global`, from Node.js or Browserified code,
-	// and use it as `root`
-	var freeGlobal = typeof global == 'object' && global;
-	if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
-		root = freeGlobal;
+const forEach = function(array, callback) {
+	const length = array.length;
+	let index = -1;
+	while (++index < length) {
+		callback(array[index]);
 	}
+};
 
-	/*--------------------------------------------------------------------------*/
+const toString = object.toString;
+const isArray = Array.isArray;
+const isObject = function(value) {
+	// This is a very simple check, but it’s good enough for what we need.
+	return toString.call(value) == '[object Object]';
+};
+const isString = function(value) {
+	return typeof value == 'string' ||
+		toString.call(value) == '[object String]';
+};
+const isNumber = function(value) {
+	return typeof value == 'number' ||
+		toString.call(value) == '[object Number]';
+};
+const isFunction = function(value) {
+	return typeof value == 'function';
+};
+const isMap = function(value) {
+	return toString.call(value) == '[object Map]';
+};
+const isSet = function(value) {
+	return toString.call(value) == '[object Set]';
+};
 
-	var object = {};
-	var hasOwnProperty = object.hasOwnProperty;
-	var forOwn = function(object, callback) {
-		var key;
-		for (key in object) {
-			if (hasOwnProperty.call(object, key)) {
-				callback(key, object[key]);
-			}
-		}
-	};
+/*--------------------------------------------------------------------------*/
 
-	var extend = function(destination, source) {
-		if (!source) {
-			return destination;
-		}
-		forOwn(source, function(key, value) {
-			destination[key] = value;
-		});
-		return destination;
-	};
+// https://mathiasbynens.be/notes/javascript-escapes#single
+const singleEscapes = {
+	'"': '\\"',
+	'\'': '\\\'',
+	'\\': '\\\\',
+	'\b': '\\b',
+	'\f': '\\f',
+	'\n': '\\n',
+	'\r': '\\r',
+	'\t': '\\t'
+	// `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
+	// '\v': '\\x0B'
+};
+const regexSingleEscape = /["'\\\b\f\n\r\t]/;
 
-	var forEach = function(array, callback) {
-		var length = array.length;
-		var index = -1;
-		while (++index < length) {
-			callback(array[index]);
-		}
-	};
+const regexDigit = /[0-9]/;
+const regexWhitelist = /<%= whitelist %>/;
 
-	var toString = object.toString;
-	var isArray = function(value) {
-		return toString.call(value) == '[object Array]';
-	};
-	var isObject = function(value) {
-		// This is a very simple check, but it’s good enough for what we need.
-		return toString.call(value) == '[object Object]';
-	};
-	var isString = function(value) {
-		return typeof value == 'string' ||
-			toString.call(value) == '[object String]';
-	};
-	var isFunction = function(value) {
-		// In a perfect world, the `typeof` check would be sufficient. However,
-		// in Chrome 1–12, `typeof /x/ == 'object'`, and in IE 6–8
-		// `typeof alert == 'object'` and similar for other host objects.
-		return typeof value == 'function' ||
-			toString.call(value) == '[object Function]';
+const jsesc = function(argument, options) {
+	const increaseIndentation = function() {
+		oldIndent = indent;
+		++options.indentLevel;
+		indent = options.indent.repeat(options.indentLevel)
 	};
-	var isMap = function(value) {
-		return toString.call(value) == '[object Map]';
+	// Handle options
+	const defaults = {
+		'escapeEverything': false,
+		'escapeEtago': false,
+		'quotes': 'single',
+		'wrap': false,
+		'es6': false,
+		'json': false,
+		'compact': true,
+		'lowercaseHex': false,
+		'numbers': 'decimal',
+		'indent': '\t',
+		'indentLevel': 0,
+		'__inline1__': false,
+		'__inline2__': false
 	};
-	var isSet = function(value) {
-		return toString.call(value) == '[object Set]';
-	};
-
-	/*--------------------------------------------------------------------------*/
-
-	// https://mathiasbynens.be/notes/javascript-escapes#single
-	var singleEscapes = {
-		'"': '\\"',
-		'\'': '\\\'',
-		'\\': '\\\\',
-		'\b': '\\b',
-		'\f': '\\f',
-		'\n': '\\n',
-		'\r': '\\r',
-		'\t': '\\t'
-		// `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
-		// '\v': '\\x0B'
-	};
-	var regexSingleEscape = /["'\\\b\f\n\r\t]/;
+	const json = options && options.json;
+	if (json) {
+		defaults.quotes = 'double';
+		defaults.wrap = true;
+	}
+	options = extend(defaults, options);
+	if (options.quotes != 'single' && options.quotes != 'double') {
+		options.quotes = 'single';
+	}
+	const quote = options.quotes == 'double' ? '"' : '\'';
+	const compact = options.compact;
+	const lowercaseHex = options.lowercaseHex;
+	let indent = options.indent.repeat(options.indentLevel);
+	let oldIndent = '';
+	const inline1 = options.__inline1__;
+	const inline2 = options.__inline2__;
+	const newLine = compact ? '' : '\n';
+	let result;
+	let isEmpty = true;
+	const useBinNumbers = options.numbers == 'binary';
+	const useOctNumbers = options.numbers == 'octal';
+	const useDecNumbers = options.numbers == 'decimal';
+	const useHexNumbers = options.numbers == 'hexadecimal';
 
-	var regexDigit = /[0-9]/;
-	var regexWhitelist = /<%= whitelist %>/;
+	if (json && argument && isFunction(argument.toJSON)) {
+		argument = argument.toJSON();
+	}
 
-	var jsesc = function(argument, options) {
-		// Handle options
-		var defaults = {
-			'escapeEverything': false,
-			'escapeEtago': false,
-			'quotes': 'single',
-			'wrap': false,
-			'es6': false,
-			'json': false,
-			'compact': true,
-			'lowercaseHex': false,
-			'indent': '\t',
-			'__indent__': ''
-		};
-		var json = options && options.json;
-		if (json) {
-			defaults.quotes = 'double';
-			defaults.wrap = true;
-		}
-		options = extend(defaults, options);
-		if (options.quotes != 'single' && options.quotes != 'double') {
-			options.quotes = 'single';
+	if (!isString(argument)) {
+		if (isMap(argument)) {
+			if (argument.size == 0) {
+				return 'new Map()';
+			}
+			if (!compact) {
+				options.__inline1__ = true;
+				options.__inline2__ = false;
+			}
+			return 'new Map(' + jsesc(Array.from(argument), options) + ')';
 		}
-		var quote = options.quotes == 'double' ? '"' : '\'';
-		var compact = options.compact;
-		var indent = options.indent;
-		var oldIndent;
-		var newLine = compact ? '' : '\n';
-		var result;
-		var isEmpty = true;
-
-		if (json && argument && isFunction(argument.toJSON)) {
-			argument = argument.toJSON();
+		if (isSet(argument)) {
+			if (argument.size == 0) {
+				return 'new Set()';
+			}
+			return 'new Set(' + jsesc(Array.from(argument), options) + ')';
 		}
-
-		if (!isString(argument)) {
-			if (isMap(argument)) {
-				if (argument.size == 0) {
-					return 'new Map()';
-				}
-				return 'new Map(' + jsesc(Array.from(argument), options) + ')';
+		if (isArray(argument)) {
+			result = [];
+			options.wrap = true;
+			if (inline1) {
+				options.__inline1__ = false;
+				options.__inline2__ = true;
 			}
-			if (isSet(argument)) {
-				if (argument.size == 0) {
-					return 'new Set()';
-				}
-				return 'new Set(' + jsesc(Array.from(argument), options) + ')';
+			if (!inline2) {
+				increaseIndentation();
 			}
-			if (isArray(argument)) {
-				result = [];
-				options.wrap = true;
-				oldIndent = options.__indent__;
-				indent += oldIndent;
-				options.__indent__ = indent;
-				forEach(argument, function(value) {
-					isEmpty = false;
-					result.push(
-						(compact ? '' : indent) +
-						jsesc(value, options)
-					);
-				});
-				if (isEmpty) {
-					return '[]';
-				}
-				return '[' + newLine + result.join(',' + newLine) + newLine +
-					(compact ? '' : oldIndent) + ']';
-			} else if (!isObject(argument)) {
-				if (json) {
-					// For some values (e.g. `undefined`, `function` objects),
-					// `JSON.stringify(value)` returns `undefined` (which isn’t valid
-					// JSON) instead of `'null'`.
-					return JSON.stringify(argument) || 'null';
+			forEach(argument, function(value) {
+				isEmpty = false;
+				if (inline2) {
+					options.__inline2__ = false;
 				}
+				result.push(
+					(compact || inline2 ? '' : indent) +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '[]';
+			}
+			if (inline2) {
+				return '[' + result.join(', ') + ']';
+			}
+			return '[' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + ']';
+		} else if (isNumber(argument)) {
+			if (json) {
+				// Some number values (e.g. `Infinity`) cannot be represented in JSON.
+				return JSON.stringify(argument);
+			}
+			if (useDecNumbers) {
 				return String(argument);
-			} else { // it’s an object
-				result = [];
-				options.wrap = true;
-				oldIndent = options.__indent__;
-				indent += oldIndent;
-				options.__indent__ = indent;
-				forOwn(argument, function(key, value) {
-					isEmpty = false;
-					result.push(
-						(compact ? '' : indent) +
-						jsesc(key, options) + ':' +
-						(compact ? '' : ' ') +
-						jsesc(value, options)
-					);
-				});
-				if (isEmpty) {
-					return '{}';
+			}
+			if (useHexNumbers) {
+				let hexadecimal = argument.toString(16);
+				if (!lowercaseHex) {
+					hexadecimal = hexadecimal.toUpperCase();
 				}
-				return '{' + newLine + result.join(',' + newLine) + newLine +
-					(compact ? '' : oldIndent) + '}';
+				return '0x' + hexadecimal;
+			}
+			if (useBinNumbers) {
+				return '0b' + argument.toString(2);
+			}
+			if (useOctNumbers) {
+				return '0o' + argument.toString(8);
+			}
+		} else if (!isObject(argument)) {
+			if (json) {
+				// For some values (e.g. `undefined`, `function` objects),
+				// `JSON.stringify(value)` returns `undefined` (which isn’t valid
+				// JSON) instead of `'null'`.
+				return JSON.stringify(argument) || 'null';
 			}
+			return String(argument);
+		} else { // it’s an object
+			result = [];
+			options.wrap = true;
+			increaseIndentation();
+			forOwn(argument, function(key, value) {
+				isEmpty = false;
+				result.push(
+					(compact ? '' : indent) +
+					jsesc(key, options) + ':' +
+					(compact ? '' : ' ') +
+					jsesc(value, options)
+				);
+			});
+			if (isEmpty) {
+				return '{}';
+			}
+			return '{' + newLine + result.join(',' + newLine) + newLine +
+				(compact ? '' : oldIndent) + '}';
 		}
+	}
 
-		var string = argument;
-		// Loop over each code unit in the string and escape it
-		var index = -1;
-		var length = string.length;
-		var first;
-		var second;
-		var codePoint;
-		result = '';
-		while (++index < length) {
-			var character = string.charAt(index);
-			if (options.es6) {
-				first = string.charCodeAt(index);
-				if ( // check if it’s the start of a surrogate pair
-					first >= 0xD800 && first <= 0xDBFF && // high surrogate
-					length > index + 1 // there is a next code unit
-				) {
-					second = string.charCodeAt(index + 1);
-					if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
-						// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
-						codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
-						var hexadecimal = codePoint.toString(16);
-						if (!options.lowercaseHex) {
-							hexadecimal = hexadecimal.toUpperCase();
-						}
-						result += '\\u{' + hexadecimal + '}';
-						index++;
-						continue;
+	const string = argument;
+	// Loop over each code unit in the string and escape it
+	let index = -1;
+	const length = string.length;
+	result = '';
+	while (++index < length) {
+		const character = string.charAt(index);
+		if (options.es6) {
+			const first = string.charCodeAt(index);
+			if ( // check if it’s the start of a surrogate pair
+				first >= 0xD800 && first <= 0xDBFF && // high surrogate
+				length > index + 1 // there is a next code unit
+			) {
+				const second = string.charCodeAt(index + 1);
+				if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
+					// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+					const codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+					let hexadecimal = codePoint.toString(16);
+					if (!lowercaseHex) {
+						hexadecimal = hexadecimal.toUpperCase();
 					}
-				}
-			}
-			if (!options.escapeEverything) {
-				if (regexWhitelist.test(character)) {
-					// It’s a printable ASCII character that is not `"`, `'` or `\`,
-					// so don’t escape it.
-					result += character;
-					continue;
-				}
-				if (character == '"') {
-					result += quote == character ? '\\"' : character;
-					continue;
-				}
-				if (character == '\'') {
-					result += quote == character ? '\\\'' : character;
+					result += '\\u{' + hexadecimal + '}';
+					++index;
 					continue;
 				}
 			}
-			if (
-				character == '\0' &&
-				!json &&
-				!regexDigit.test(string.charAt(index + 1))
-			) {
-				result += '\\0';
+		}
+		if (!options.escapeEverything) {
+			if (regexWhitelist.test(character)) {
+				// It’s a printable ASCII character that is not `"`, `'` or `\`,
+				// so don’t escape it.
+				result += character;
 				continue;
 			}
-			if (regexSingleEscape.test(character)) {
-				// no need for a `hasOwnProperty` check here
-				result += singleEscapes[character];
+			if (character == '"') {
+				result += quote == character ? '\\"' : character;
 				continue;
 			}
-			var charCode = character.charCodeAt(0);
-			var hexadecimal = charCode.toString(16);
-			if (!options.lowercaseHex) {
-				hexadecimal = hexadecimal.toUpperCase();
+			if (character == '\'') {
+				result += quote == character ? '\\\'' : character;
+				continue;
 			}
-			var longhand = hexadecimal.length > 2 || json;
-			var escaped = '\\' + (longhand ? 'u' : 'x') +
-				('0000' + hexadecimal).slice(longhand ? -4 : -2);
-			result += escaped;
+		}
+		if (
+			character == '\0' &&
+			!json &&
+			!regexDigit.test(string.charAt(index + 1))
+		) {
+			result += '\\0';
 			continue;
 		}
-		if (options.wrap) {
-			result = quote + result + quote;
+		if (regexSingleEscape.test(character)) {
+			// no need for a `hasOwnProperty` check here
+			result += singleEscapes[character];
+			continue;
 		}
-		if (options.escapeEtago) {
-			// https://mathiasbynens.be/notes/etago
-			return result.replace(/<\/(script|style)/gi, '<\\/$1');
+		const charCode = character.charCodeAt(0);
+		let hexadecimal = charCode.toString(16);
+		if (!lowercaseHex) {
+			hexadecimal = hexadecimal.toUpperCase();
 		}
-		return result;
-	};
-
-	jsesc.version = '<%= version %>';
-
-	/*--------------------------------------------------------------------------*/
-
-	// Some AMD build optimizers, like r.js, check for specific condition patterns
-	// like the following:
-	if (
-		typeof define == 'function' &&
-		typeof define.amd == 'object' &&
-		define.amd
-	) {
-		define(function() {
-			return jsesc;
-		});
-	}	else if (freeExports && !freeExports.nodeType) {
-		if (freeModule) { // in Node.js or RingoJS v0.8.0+
-			freeModule.exports = jsesc;
-		} else { // in Narwhal or RingoJS v0.7.0-
-			freeExports.jsesc = jsesc;
-		}
-	} else { // in Rhino or a web browser
-		root.jsesc = jsesc;
+		const longhand = hexadecimal.length > 2 || json;
+		const escaped = '\\' + (longhand ? 'u' : 'x') +
+			('0000' + hexadecimal).slice(longhand ? -4 : -2);
+		result += escaped;
+		continue;
 	}
+	if (options.wrap) {
+		result = quote + result + quote;
+	}
+	if (options.escapeEtago) {
+		// https://mathiasbynens.be/notes/etago
+		return result.replace(/<\/(script|style)/gi, '<\\/$1');
+	}
+	return result;
+};
+
+jsesc.version = '<%= version %>';
 
-}(this));
+module.exports = jsesc;
diff --git a/tests/tests.js b/tests/tests.js
index 5f53a14..51153f3 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -1,136 +1,134 @@
-(function(root) {
-	'use strict';
+'use strict';
 
-	var noop = Function.prototype;
+const assert = require('assert');
+const jsesc = require('../jsesc.js');
 
-	var load = (typeof require == 'function' && !(root.define && define.amd)) ?
-		require :
-		(!root.document && root.java && root.load) || noop;
-
-	var QUnit = (function() {
-		return root.QUnit || (
-			root.addEventListener || (root.addEventListener = noop),
-			root.setTimeout || (root.setTimeout = noop),
-			root.QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
-			addEventListener === noop && delete root.addEventListener,
-			root.QUnit
-		);
-	}());
-
-	var qe = load('../node_modules/qunit-extras/qunit-extras.js');
-	if (qe) {
-		qe.runInContext(root);
-	}
-
-	// Extend `Object.prototype` to see if this library can handle it.
-	Object.prototype['\u2665'] = '...';
-
-	/** The `regenerate` object to test */
-	var jsesc = root.jsesc || (root.jsesc = (
-		jsesc = load('../jsesc.js') || root.jsesc,
-		jsesc = jsesc.jsesc || jsesc
-	));
-
-	/*--------------------------------------------------------------------------*/
-
-	// Quick and dirty test to see if we’re in PhantomJS or Node
-	var isNode = typeof process != 'undefined' && process.argv &&
-		process.argv[0].slice(-4) == 'node';
-	var runExtendedTests = root.phantom || isNode;
-
-	// explicitly call `QUnit.module()` instead of `module()`
-	// in case we are in a CLI environment
-	QUnit.module('jsesc');
-
-	test('common usage', function() {
-		equal(
+describe('common usage', function() {
+	it('works correctly for common operations', function() {
+		assert.equal(
 			typeof jsesc.version,
 			'string',
 			'`jsesc.version` must be a string'
 		);
-		equal(
+		assert.equal(
 			jsesc('\0\x31'),
 			'\\x001',
 			'`\\0` followed by `1`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\0\x38'),
 			'\\x008',
 			'`\\0` followed by `8`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\0\x39'),
 			'\\x009',
 			'`\\0` followed by `9`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\0a'),
 			'\\0a',
 			'`\\0` followed by `a`'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo"bar\'baz', {
 				'quotes': 'LOLWAT' // invalid setting
 			}),
 			'foo"bar\\\'baz',
 			'Invalid `quotes` setting'
 		);
-		equal(
+		assert.equal(
 			jsesc('\\x00'),
 			'\\\\x00',
 			'`\\\\x00` shouldn’t be changed to `\\\\0`'
 		);
-		equal(
+		assert.equal(
 			jsesc('a\\x00'),
 			'a\\\\x00',
 			'`a\\\\x00` shouldn’t be changed to `\\\\0`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\\\x00'),
 			'\\\\\\0',
 			'`\\\\\\x00` should be changed to `\\\\\\0`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\\\\x00'),
 			'\\\\\\\\x00',
 			'`\\\\\\\\x00` shouldn’t be changed to `\\\\\\\\0`'
 		);
-		equal(
+		assert.equal(
 			jsesc('lolwat"foo\'bar', {
 				'escapeEverything': true
 			}),
 			'\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72',
 			'escapeEverything'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo</script>bar</style>baz</script>qux', {
 				'escapeEtago': true
 			}),
 			'foo<\\/script>bar<\\/style>baz<\\/script>qux',
 			'escapeEtago'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo</sCrIpT>bar</STYLE>baz</SCRIPT>qux', {
 				'escapeEtago': true
 			}),
 			'foo<\\/sCrIpT>bar<\\/STYLE>baz<\\/SCRIPT>qux',
 			'escapeEtago'
 		);
-		equal(
+		assert.equal(
+			jsesc([0x42, 0x1337], {
+				'numbers': 'decimal'
+			}),
+			'[66,4919]',
+			'`numbers: \'decimal\'` (default)'
+		);
+		assert.equal(
+			jsesc([0x42, 0x1337], {
+				'numbers': 'binary'
+			}),
+			'[0b1000010,0b1001100110111]',
+			'`numbers: \'binary\'`'
+		);
+		assert.equal(
+			jsesc([0x42, 0x1337, NaN, Infinity], {
+				'numbers': 'binary',
+				'json': true
+			}),
+			'[66,4919,null,null]',
+			'`json: true` takes precedence over `numbers: \'binary\'`'
+		);
+		assert.equal(
+			jsesc([0x42, 0x1337], {
+				'numbers': 'octal'
+			}),
+			'[0o102,0o11467]',
+			'`numbers: \'octal\'`'
+		);
+		assert.equal(
+			jsesc([0x42, 0x1337], {
+				'numbers': 'hexadecimal'
+			}),
+			'[0x42,0x1337]',
+			'`numbers: \'hexadecimal\'`'
+		);
+		assert.equal(
 			jsesc('a\uD834\uDF06b', {
 				'es6': true
 			}),
 			'a\\u{1D306}b',
 			'es6'
 		);
-		equal(
+		assert.equal(
 			jsesc('a\uD834\uDF06b\uD83D\uDCA9c', {
 				'es6': true
 			}),
 			'a\\u{1D306}b\\u{1F4A9}c',
 			'es6'
 		);
-		equal(
+		assert.equal(
 			jsesc('a\uD834\uDF06b\uD83D\uDCA9c', {
 				'es6': true,
 				'escapeEverything': true
@@ -138,28 +136,28 @@
 			'\\x61\\u{1D306}\\x62\\u{1F4A9}\\x63',
 			'es6 + escapeEverything'
 		);
-		equal(
+		assert.equal(
 			jsesc({}, {
 				'compact': true
 			}),
 			'{}',
 			'Stringifying an empty object with `compact: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc({}, {
 				'compact': false
 			}),
 			'{}',
 			'Stringifying an empty object with `compact: false`'
 		);
-		equal(
+		assert.equal(
 			jsesc([], {
 				'compact': true
 			}),
 			'[]',
 			'Stringifying an empty array with `compact: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc([], {
 				'compact': false
 			}),
@@ -167,26 +165,42 @@
 			'Stringifying an empty array with `compact: false`'
 		);
 		// Stringifying flat objects containing only string values
-		equal(
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }),
 			'{\'foo\\0bar\\uFFFDbaz\':\'foo\\0bar\\uFFFDbaz\'}',
 			'Stringifying a flat object with default settings`'
 		);
-		equal(
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
 				'quotes': 'double'
 			}),
 			'{"foo\\0bar\\uFFFDbaz":"foo\\0bar\\uFFFDbaz"}',
 			'Stringifying a flat object with `quotes: \'double\'`'
 		);
-		equal(
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
 				'compact': false
 			}),
 			'{\n\t\'foo\\0bar\\uFFFDbaz\': \'foo\\0bar\\uFFFDbaz\'\n}',
 			'Stringifying a flat object with `compact: false`'
 		);
-		equal(
+		assert.equal(
+			jsesc(['a', 'b', 'c'], {
+				'compact': false,
+				'indentLevel': 1
+			}),
+			'[\n\t\t\'a\',\n\t\t\'b\',\n\t\t\'c\'\n\t]',
+			'`indentLevel: 1`'
+		);
+		assert.equal(
+			jsesc(['a', 'b', 'c'], {
+				'compact': false,
+				'indentLevel': 2
+			}),
+			'[\n\t\t\t\'a\',\n\t\t\t\'b\',\n\t\t\t\'c\'\n\t\t]',
+			'`indentLevel: 2`'
+		);
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
 				'compact': false,
 				'indent': '  '
@@ -194,7 +208,7 @@
 			'{\n  \'foo\\0bar\\uFFFDbaz\': \'foo\\0bar\\uFFFDbaz\'\n}',
 			'Stringifying a flat object with `compact: false, indent: \'  \'`'
 		);
-		equal(
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
 				'escapeEverything': true
 			}),
@@ -202,102 +216,130 @@
 			'Stringifying a flat object with `escapeEverything: true`'
 		);
 		// Stringifying flat arrays containing only string values
-		equal(
+		assert.equal(
 			jsesc(['foo\x00bar\uFFFDbaz', '\xA9'], {
 				'escapeEverything': true
 			}),
 			'[\'\\x66\\x6F\\x6F\\0\\x62\\x61\\x72\\uFFFD\\x62\\x61\\x7A\',\'\\xA9\']',
 			'Stringifying a flat array with `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc(['foo\x00bar\uFFFDbaz', '\xA9'], {
 				'compact': false
 			}),
 			'[\n\t\'foo\\0bar\\uFFFDbaz\',\n\t\'\\xA9\'\n]',
 			'Stringifying a flat array with `compact: false`'
 		);
-		// Maps
-		if (typeof Map != 'undefined') {
-			equal(
-				jsesc(
-					new Map([])
-				),
-				'new Map()',
-				'Stringifying an empty Map'
-			);
-			equal(
-				jsesc(
-					new Map([
-						['a', 1],
-						['b', 2]
-					]),
-					{
-						'compact': true
-					}
-				),
-				'new Map([[\'a\',1],[\'b\',2]])',
-				'Stringifying a Map with `compact: true`'
-			);
-			equal(
-				jsesc(
-					new Map([
-						['a', 1],
-						['b', 2]
-					]),
-					{
-						'compact': false
-					}
-				),
-				'new Map([\n\t[\n\t\t\'a\',\n\t\t1\n\t],\n\t[\n\t\t\'b\',\n\t\t2\n\t]\n])',
-				'Stringifying a Map with `compact: false`'
-			);
-		}
-		if (typeof Set != 'undefined') {
-			equal(
-				jsesc(
-					new Set([])
-				),
-				'new Set()',
-				'Stringifying an empty Set'
-			);
-			equal(
-				jsesc(
-					new Set([
-						['a'],
-						'b',
-						{}
-					]),
-					{
-						'compact': true
-					}
-				),
-				'new Set([[\'a\'],\'b\',{}])',
-				'Stringifying a Set with `compact: true`'
-			);
-			equal(
-				jsesc(
-					new Set([
-						['a'],
-						'b',
-						{}
-					]),
-					{
-						'compact': false
-					}
-				),
-				'new Set([\n\t[\n\t\t\'a\'\n\t],\n\t\'b\',\n\t{}\n])',
-				'Stringifying a Set with `compact: false`'
-			);
-		}
+		assert.equal(
+			jsesc(
+				new Map([])
+			),
+			'new Map()',
+			'Stringifying an empty Map'
+		);
+		assert.equal(
+			jsesc(
+				new Map([
+					['a', 1],
+					['b', 2]
+				]),
+				{
+					'compact': true
+				}
+			),
+			'new Map([[\'a\',1],[\'b\',2]])',
+			'Stringifying a Map with `compact: true`'
+		);
+		assert.equal(
+			jsesc(
+				new Map([
+					['a', 1],
+					['b', 2]
+				]),
+				{
+					'compact': false
+				}
+			),
+			'new Map([\n\t[\'a\', 1],\n\t[\'b\', 2]\n])',
+			'Stringifying a Map with `compact: false`'
+		);
+		assert.equal(
+			jsesc(
+				new Map([
+					['a', 1],
+					['b', [
+						'a',
+						'nested',
+						'array'
+					]]
+				]),
+				{
+					'compact': false
+				}
+			),
+			'new Map([\n\t[\'a\', 1],\n\t[\'b\', [\n\t\t\'a\',\n\t\t\'nested\',\n\t\t\'array\'\n\t]]\n])',
+			'Stringifying a Map with `compact: false`'
+		);
+		assert.equal(
+			jsesc(
+				new Map([
+					['a', 1],
+					['b', new Map([
+						['x', 2],
+						['y', 3]
+					])]
+				]),
+				{
+					'compact': false
+				}
+			),
+			'new Map([\n\t[\'a\', 1],\n\t[\'b\', new Map([\n\t\t[\'x\', 2],\n\t\t[\'y\', 3]\n\t])]\n])',
+			'Stringifying a Map with `compact: false`'
+		);
+		assert.equal(
+			jsesc(
+				new Set([])
+			),
+			'new Set()',
+			'Stringifying an empty Set'
+		);
+		assert.equal(
+			jsesc(
+				new Set([
+					['a'],
+					'b',
+					{}
+				]),
+				{
+					'compact': true
+				}
+			),
+			'new Set([[\'a\'],\'b\',{}])',
+			'Stringifying a Set with `compact: true`'
+		);
+		assert.equal(
+			jsesc(
+				new Set([
+					['a'],
+					'b',
+					{}
+				]),
+				{
+					'compact': false
+				}
+			),
+			'new Set([\n\t[\n\t\t\'a\'\n\t],\n\t\'b\',\n\t{}\n])',
+			'Stringifying a Set with `compact: false`'
+		);
 		// JSON
-		equal(
+		assert.equal(
 			jsesc('foo\x00bar\xFF\uFFFDbaz', {
 				'json': true
 			}),
 			'"foo\\u0000bar\\u00FF\\uFFFDbaz"',
 			'JSON-stringifying a string'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo\x00bar\uFFFDbaz', {
 				'escapeEverything': true,
 				'json': true
@@ -305,7 +347,7 @@
 			'"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"',
 			'JSON-stringifying a string with `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
 				'escapeEverything': true,
 				'json': true
@@ -313,7 +355,7 @@
 			'{"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A":"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"}',
 			'JSON-stringifying a flat object with `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc(['foo\x00bar\uFFFDbaz', 'foo\x00bar\uFFFDbaz'], {
 				'escapeEverything': true,
 				'json': true
@@ -321,7 +363,7 @@
 			'["\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A","\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"]',
 			'JSON-stringifying a flat array with `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo\x00bar', {
 				'json': true,
 				'wrap': false // override default `wrap: true` when `json` is enabled
@@ -329,7 +371,7 @@
 			'foo\\u0000bar',
 			'Escaping as JSON with `wrap: false`'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo "\x00" bar', {
 				'json': true,
 				'wrap': false // override default `wrap: true` when `json` is enabled
@@ -337,7 +379,7 @@
 			'foo \\"\\u0000\\" bar',
 			'Escaping as JSON with `wrap: false` escapes double quotes correctly'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo "\x00" bar \' qux', {
 				'json': true,
 				'quotes': 'single', // override default `quotes: 'double'` when `json` is enabled
@@ -346,7 +388,7 @@
 			'foo "\\u0000" bar \\\' qux',
 			'Escaping as JSON with `wrap: false, quotes: \'single\'`'
 		);
-		equal(
+		assert.equal(
 			jsesc('foo\uD834\uDF06bar\xA9baz', {
 				'json': true,
 				'es6': true // override default `es6: false` when `json` is enabled
@@ -354,7 +396,7 @@
 			'"foo\\u{1D306}bar\\u00A9baz"',
 			'Escaping as JSON with `es6: true`'
 		);
-		var tmp = {
+		const tmp = {
 			'shouldn\u2019t be here': 10,
 			'toJSON': function() {
 				return {
@@ -364,31 +406,39 @@
 				};
 			}
 		};
-		equal(
+		assert.equal(
 			jsesc(tmp, { 'json' : true }),
 			'{"hello":"world","\\uD83D\\uDCA9":"foo","pile":"\\uD83D\\uDCA9"}',
 			'`toJSON` methods are called when `json: true`'
 		);
-		notEqual(
+		assert.notEqual(
 			jsesc(tmp),
 			'{"hello":"world","\\uD83D\\uDCA9":"foo","pile":"\\uD83D\\uDCA9"}',
 			'`toJSON` methods are not called when `json: false`'
 		);
-		equal(
+		assert.equal(
+			jsesc(42, {
+				'numbers': 'hexadecimal',
+				'lowercaseHex': true
+			}),
+			'0x2a',
+			'Hexadecimal integeral literals are lowercase when `lowercaseHex: true`'
+		);
+		assert.equal(
 			jsesc('\u2192\xE9', {
 				'lowercaseHex': true
 			}),
 			'\\u2192\\xe9',
 			'Alphabetical hexadecimal digits are lowercase when `lowercaseHex: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\u2192\xE9', {
 				'lowercaseHex': false
 			}),
 			'\\u2192\\xE9',
 			'Alphabetical hexadecimal digits are uppercase when `lowercaseHex: false`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\u2192\xE9', {
 				'lowercaseHex': true,
 				'json': true
@@ -396,7 +446,7 @@
 			'"\\u2192\\u00e9"',
 			'Alphabetical hexadecimal digits are lowercase when `lowercaseHex: false` and `json: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\u2192\xe9', {
 				'lowercaseHex': false,
 				'json': true
@@ -404,7 +454,7 @@
 			'"\\u2192\\u00E9"',
 			'Alphabetical hexadecimal digits are uppercase when `lowercaseHex: false` and `json: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\xE7\xE7a\xE7\xE7', {
 				'lowercaseHex': true,
 				'escapeEverything': true
@@ -412,7 +462,7 @@
 			'\\xe7\\xe7\\x61\\xe7\\xe7',
 			'Alphabetical hexadecimal digits are lowercase when `lowercaseHex: true` and `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\xE7\xE7a\xE7\xE7', {
 				'lowercaseHex': false,
 				'escapeEverything': true
@@ -420,7 +470,7 @@
 			'\\xE7\\xE7\\x61\\xE7\\xE7',
 			'Alphabetical hexadecimal digits are uppercase when `lowercaseHex: false` and `escapeEverything: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\u2192\xE9\uD83D\uDCA9', {
 				'lowercaseHex': true,
 				'es6': true
@@ -428,7 +478,7 @@
 			'\\u2192\\xe9\\u{1f4a9}',
 			'Alphabetical hexadecimal digits are lowercase when `lowercaseHex: true` and `es6: true`'
 		);
-		equal(
+		assert.equal(
 			jsesc('\u2192\xE9\uD83D\uDCA9', {
 				'lowercaseHex': false,
 				'es6': true
@@ -437,568 +487,83 @@
 			'Alphabetical hexadecimal digits are uppercase when `lowercaseHex: false` and `es6: true`'
 		);
 	});
+});
 
-	if (runExtendedTests) {
-		test('advanced tests', function() {
-			var map = function(array, fn) {
-				var length = array.length;
-				while (length--) {
-					array[length] = fn(array[length]);
-				}
-				return array;
-			};
-
-			// taken from https://mths.be/punycode
-			var stringFromCharCode = String.fromCharCode;
-			var ucs2encode = function(value) {
-				var output = '';
-				if (value > 0xFFFF) {
-					value -= 0x10000;
-					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
-					value = 0xDC00 | value & 0x3FF;
-				}
-				output += stringFromCharCode(value);
-				return output;
-			};
-
-			var allSymbols = '';
-			var codePoint;
-			var symbol = '';
-			// Generate strings based on code points. Trickier than it seems:
-			// https://mathiasbynens.be/notes/javascript-encoding
-			for (codePoint = 0x000000; codePoint <= 0x10FFFF; codePoint += 0xF) {
-				symbol = ucs2encode(codePoint);
-				// ok(
-				// 	eval('\'' + jsesc(symbol) + '\'') == symbol,
-				// 	'U+' + codePoint.toString(16).toUpperCase()
-				// );
-				allSymbols += symbol + ' ';
-			}
-
-			ok(
-				eval('\'' + jsesc(allSymbols) + '\'') == allSymbols,
-				'All Unicode symbols, space-separated, default quote type (single quotes)'
-			);
-			ok(
-				eval('\'' + jsesc(allSymbols, {
-					'quotes': 'single'
-				}) + '\'') == allSymbols,
-				'All Unicode symbols, space-separated, single quotes'
-			);
-			ok(
-				eval(jsesc(allSymbols, {
-					'quotes': 'single',
-					'wrap': true
-				})) == allSymbols,
-				'All Unicode symbols, space-separated, single quotes, auto-wrap'
-			);
-			ok(
-				eval('"' + jsesc(allSymbols, {
-					'quotes': 'double'
-				}) + '"') == allSymbols,
-				'All Unicode symbols, space-separated, double quotes'
-			);
-			ok(
-				eval(jsesc(allSymbols, {
-					'quotes': 'double',
-					'wrap': true
-				})) == allSymbols,
-				'All Unicode symbols, space-separated, double quotes, auto-wrap'
-			);
-
-			// Some of these depend on `JSON.parse()`, so only test them in Node
-			if (isNode) {
-				var testArray = [
-					undefined, Infinity, new Number(Infinity), -Infinity,
-					new Number(-Infinity), 0, new Number(0), -0, new Number(-0), +0,
-					new Number(+0), new Function(), 'str',
-					function zomg() { return 'desu'; }, null, true, new Boolean(true),
-					false, new Boolean(false), {
-						"foo": 42, "hah": [ 1, 2, 3, { "foo" : 42 } ]
-					}
-				];
-				equal(
-					jsesc(testArray, {
-						'json': false
-					}),
-					'[undefined,Infinity,Infinity,-Infinity,-Infinity,0,0,0,0,0,0,function anonymous() {\n\n},\'str\',function zomg() { return \'desu\'; },null,true,true,false,false,{\'foo\':42,\'hah\':[1,2,3,{\'foo\':42}]}]',
-					'Escaping a non-flat array with all kinds of values'
-				);
-				equal(
-					jsesc(testArray, {
-						'json': true
-					}),
-					'[null,null,null,null,null,0,0,0,0,0,0,null,"str",null,null,true,true,false,false,{"foo":42,"hah":[1,2,3,{"foo":42}]}]',
-					'Escaping a non-flat array with all kinds of values, with `json: true`'
-				);
-				equal(
-					jsesc(testArray, {
-						'json': true,
-						'compact': false
-					}),
-					'[\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\tnull,\n\t"str",\n\tnull,\n\tnull,\n\ttrue,\n\ttrue,\n\tfalse,\n\tfalse,\n\t{\n\t\t"foo": 42,\n\t\t"hah": [\n\t\t\t1,\n\t\t\t2,\n\t\t\t3,\n\t\t\t{\n\t\t\t\t"foo": 42\n\t\t\t}\n\t\t]\n\t}\n]',
-					'Escaping a non-flat array with all kinds of values, with `json: true, compact: false`'
-				);
-			}
-		});
+describe('advanced tests', function() {
+	let allSymbols = '';
+	// Generate strings based on code points. Trickier than it seems:
+	// https://mathiasbynens.be/notes/javascript-encoding
+	for (let codePoint = 0x000000; codePoint <= 0x10FFFF; codePoint += 0xF) {
+		const symbol = String.fromCodePoint(codePoint);
+		// ok(
+		// 	eval('\'' + jsesc(symbol) + '\'') == symbol,
+		// 	'U+' + codePoint.toString(16).toUpperCase()
+		// );
+		allSymbols += symbol + ' ';
 	}
+	it('works correctly for advanced operations', function() {
+		assert.ok(
+			eval('\'' + jsesc(allSymbols) + '\'') == allSymbols,
+			'All Unicode symbols, space-separated, default quote type (single quotes)'
+		);
+		assert.ok(
+			eval('\'' + jsesc(allSymbols, {
+				'quotes': 'single'
+			}) + '\'') == allSymbols,
+			'All Unicode symbols, space-separated, single quotes'
+		);
+		assert.ok(
+			eval(jsesc(allSymbols, {
+				'quotes': 'single',
+				'wrap': true
+			})) == allSymbols,
+			'All Unicode symbols, space-separated, single quotes, auto-wrap'
+		);
+		assert.ok(
+			eval('"' + jsesc(allSymbols, {
+				'quotes': 'double'
+			}) + '"') == allSymbols,
+			'All Unicode symbols, space-separated, double quotes'
+		);
+		assert.ok(
+			eval(jsesc(allSymbols, {
+				'quotes': 'double',
+				'wrap': true
+			})) == allSymbols,
+			'All Unicode symbols, space-separated, double quotes, auto-wrap'
+		);
 
-	// Test binary
-	if (isNode) {
-		asyncTest('jsesc binary', function() {
-
-			var exec = require('child_process').exec;
-
-			var shellTest = function(command, callback) {
-				exec(command, function(error, stdout, stderr) {
-					callback({
-						'stdout': stdout,
-						'stderr': stderr,
-						'exitStatus': error ? error.code : 0
-					});
-				});
-			};
-
-			var tests = [
-				{
-					'description': 'No arguments',
-					'command': './bin/jsesc',
-					'expected': {
-						'exitStatus': 1
-					}
-				},
-				{
-					'description': '-h option',
-					'command': './bin/jsesc -h',
-					'expected': {
-						'exitStatus': 1
-					}
-				},
-				{
-					'description': '--help option',
-					'command': './bin/jsesc --help',
-					'expected': {
-						'exitStatus': 1
-					}
-				},
-				{
-					'description': '-v option',
-					'command': './bin/jsesc -v',
-					'expected': {
-						'exitStatus': 1
-					}
-				},
-				{
-					'description': '--version option',
-					'command': './bin/jsesc --version',
-					'expected': {
-						'exitStatus': 1
-					}
-				},
-				{
-					'description': 'No options',
-					'command': './bin/jsesc "f\xF6o \u2665 b\xE5r \uD834\uDF06 baz"',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': 'No options, piping content',
-					'command': 'echo "f\xF6o \u2665 b\xE5r \uD834\uDF06 baz" | ./bin/jsesc',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-s option',
-					'command': './bin/jsesc -s f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-s option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -s',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--single-quotes option',
-					'command': './bin/jsesc --single-quotes f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--single-quotes option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --single-quotes',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-d option',
-					'command': './bin/jsesc -d f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-d option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -d',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--double-quotes option',
-					'command': './bin/jsesc --double-quotes f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--double-quotes option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --double-quotes',
-					'expected': {
-						'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-w option',
-					'command': './bin/jsesc -w f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-w option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -w',
-					'expected': {
-						'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--wrap option',
-					'command': './bin/jsesc --wrap f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--wrap option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --wrap',
-					'expected': {
-						'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-6 option',
-					'command': './bin/jsesc -6 a\uD834\uDF06b\uD83D\uDCA9c',
-					'expected': {
-						'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-6 option, piping content',
-					'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc -6',
-					'expected': {
-						'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-
-				{
-					'description': '--es6 option',
-					'command': './bin/jsesc --es6 a\uD834\uDF06b\uD83D\uDCA9c',
-					'expected': {
-						'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--es6 option, piping content',
-					'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc --es6',
-					'expected': {
-						'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-e option',
-					'command': './bin/jsesc -e f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-e option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -e',
-					'expected': {
-						'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--escape-everything option',
-					'command': './bin/jsesc --escape-everything f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--escape-everything option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --escape-everything',
-					'expected': {
-						'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-t option',
-					'command': './bin/jsesc -t "foo</script>bar"',
-					'expected': {
-						'stdout': 'foo<\\/script>bar\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-t option, piping content',
-					'command': 'echo "foo</script>bar" | ./bin/jsesc -t',
-					'expected': {
-						'stdout': 'foo<\\/script>bar\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--escape-etago option',
-					'command': './bin/jsesc --escape-etago "foo</script>bar"',
-					'expected': {
-						'stdout': 'foo<\\/script>bar\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--escape-etago option, piping content',
-					'command': 'echo "foo</script>bar" | ./bin/jsesc --escape-etago',
-					'expected': {
-						'stdout': 'foo<\\/script>bar\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-l option',
-					'command': './bin/jsesc -l a\uD834\uDF06b\uD83D\uDCA9c',
-					'expected': {
-						'stdout': 'a\\ud834\\udf06b\\ud83d\\udca9c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-l option, piping content',
-					'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc -l',
-					'expected': {
-						'stdout': 'a\\ud834\\udf06b\\ud83d\\udca9c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--lowercase-hex option',
-					'command': './bin/jsesc --lowercase-hex a\uD834\uDF06b\uD83D\uDCA9c',
-					'expected': {
-						'stdout': 'a\\ud834\\udf06b\\ud83d\\udca9c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--lowercase-hex option, piping content',
-					'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc --lowercase-hex',
-					'expected': {
-						'stdout': 'a\\ud834\\udf06b\\ud83d\\udca9c\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-j option',
-					'command': './bin/jsesc -j f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-j option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -j',
-					'expected': {
-						'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--json option',
-					'command': './bin/jsesc --json f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
-					'expected': {
-						'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--json option, piping content',
-					'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --json',
-					'expected': {
-						'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-o option',
-					'command': './bin/jsesc -o \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
-					'expected': {
-						'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-o option, piping content',
-					'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc -o',
-					'expected': {
-						'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--object option',
-					'command': './bin/jsesc --object \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
-					'expected': {
-						'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--object option, piping content',
-					'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --object',
-					'expected': {
-						'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-p option',
-					'command': './bin/jsesc --json -p \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
-					'expected': {
-						'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '-p option, piping content',
-					'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --json -p',
-					'expected': {
-						'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--pretty option',
-					'command': './bin/jsesc --json --pretty \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
-					'expected': {
-						'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				},
-				{
-					'description': '--pretty option, piping content',
-					'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --json --pretty',
-					'expected': {
-						'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
-						'stderr': '',
-						'exitStatus': 0
-					}
-				}
-			];
-			var counter = tests.length;
-			function done() {
-				--counter || QUnit.start();
+		// Some of these depend on `JSON.parse()`, so only test them in Node
+		const testArray = [
+			undefined, Infinity, new Number(Infinity), -Infinity,
+			new Number(-Infinity), 0, new Number(0), -0, new Number(-0), +0,
+			new Number(+0), new Function(), 'str',
+			function zomg() { return 'desu'; }, null, true, new Boolean(true),
+			false, new Boolean(false), {
+				"foo": 42, "hah": [ 1, 2, 3, { "foo" : 42 } ]
 			}
-
-			tests.forEach(function(object) {
-				shellTest(object.command, function(data) {
-					// We can’t use `deepEqual` since sometimes not all expected values are provided
-					Object.keys(object.expected).forEach(function(key) {
-						equal(object.expected[key], data[key], object.description);
-					});
-					done();
-				});
-			});
-
-		});
-	}
-
-	/*--------------------------------------------------------------------------*/
-
-	// configure QUnit and call `QUnit.start()` for
-	// Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
-	if (!root.document || root.phantom) {
-		QUnit.config.noglobals = true;
-		QUnit.start();
-	}
-}(typeof global == 'object' && global || this));
+		];
+		assert.equal(
+			jsesc(testArray, {
+				'json': false
+			}),
+			'[undefined,Infinity,Infinity,-Infinity,-Infinity,0,0,0,0,0,0,function anonymous() {\n\n},\'str\',function zomg() { return \'desu\'; },null,true,true,false,false,{\'foo\':42,\'hah\':[1,2,3,{\'foo\':42}]}]',
+			'Escaping a non-flat array with all kinds of values'
+		);
+		assert.equal(
+			jsesc(testArray, {
+				'json': true
+			}),
+			'[null,null,null,null,null,0,0,0,0,0,0,null,"str",null,null,true,true,false,false,{"foo":42,"hah":[1,2,3,{"foo":42}]}]',
+			'Escaping a non-flat array with all kinds of values, with `json: true`'
+		);
+		assert.equal(
+			jsesc(testArray, {
+				'json': true,
+				'compact': false
+			}),
+			'[\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\tnull,\n\t"str",\n\tnull,\n\tnull,\n\ttrue,\n\ttrue,\n\tfalse,\n\tfalse,\n\t{\n\t\t"foo": 42,\n\t\t"hah": [\n\t\t\t1,\n\t\t\t2,\n\t\t\t3,\n\t\t\t{\n\t\t\t\t"foo": 42\n\t\t\t}\n\t\t]\n\t}\n]',
+			'Escaping a non-flat array with all kinds of values, with `json: true, compact: false`'
+		);
+	}).timeout(15000);
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-jsesc.git



More information about the Pkg-javascript-commits mailing list