aboutsummaryrefslogtreecommitdiff
path: root/node_modules/source-map-support/test.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-28 00:38:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-28 00:40:43 +0200
commit7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 (patch)
tree6de9a1aebd150a23b7f8c273ec657a5d0a18fe3e /node_modules/source-map-support/test.js
parent963b7a41feb29cc4be090a2446bdfe0c1f1bcd81 (diff)
add linting (and some initial fixes)
Diffstat (limited to 'node_modules/source-map-support/test.js')
-rw-r--r--node_modules/source-map-support/test.js581
1 files changed, 581 insertions, 0 deletions
diff --git a/node_modules/source-map-support/test.js b/node_modules/source-map-support/test.js
new file mode 100644
index 000000000..d7c593d7d
--- /dev/null
+++ b/node_modules/source-map-support/test.js
@@ -0,0 +1,581 @@
+require('./source-map-support').install({
+ emptyCacheBetweenOperations: true // Needed to be able to test for failure
+});
+
+var SourceMapGenerator = require('source-map').SourceMapGenerator;
+var child_process = require('child_process');
+var assert = require('assert');
+var fs = require('fs');
+
+function compareLines(actual, expected) {
+ assert(actual.length >= expected.length, 'got ' + actual.length + ' lines but expected at least ' + expected.length + ' lines');
+ for (var i = 0; i < expected.length; i++) {
+ // Some tests are regular expressions because the output format changed slightly between node v0.9.2 and v0.9.3
+ if (expected[i] instanceof RegExp) {
+ assert(expected[i].test(actual[i]), JSON.stringify(actual[i]) + ' does not match ' + expected[i]);
+ } else {
+ assert.equal(actual[i], expected[i]);
+ }
+ }
+}
+
+function createEmptySourceMap() {
+ return new SourceMapGenerator({
+ file: '.generated.js',
+ sourceRoot: '.'
+ });
+}
+
+function createSourceMapWithGap() {
+ var sourceMap = createEmptySourceMap();
+ sourceMap.addMapping({
+ generated: { line: 100, column: 0 },
+ original: { line: 100, column: 0 },
+ source: '.original.js'
+ });
+ return sourceMap;
+}
+
+function createSingleLineSourceMap() {
+ var sourceMap = createEmptySourceMap();
+ sourceMap.addMapping({
+ generated: { line: 1, column: 0 },
+ original: { line: 1, column: 0 },
+ source: '.original.js'
+ });
+ return sourceMap;
+}
+
+function createSecondLineSourceMap() {
+ var sourceMap = createEmptySourceMap();
+ sourceMap.addMapping({
+ generated: { line: 2, column: 0 },
+ original: { line: 1, column: 0 },
+ source: '.original.js'
+ });
+ return sourceMap;
+}
+
+function createMultiLineSourceMap() {
+ var sourceMap = createEmptySourceMap();
+ for (var i = 1; i <= 100; i++) {
+ sourceMap.addMapping({
+ generated: { line: i, column: 0 },
+ original: { line: 1000 + i, column: 99 + i },
+ source: 'line' + i + '.js'
+ });
+ }
+ return sourceMap;
+}
+
+function createMultiLineSourceMapWithSourcesContent() {
+ var sourceMap = createEmptySourceMap();
+ var original = new Array(1001).join('\n');
+ for (var i = 1; i <= 100; i++) {
+ sourceMap.addMapping({
+ generated: { line: i, column: 0 },
+ original: { line: 1000 + i, column: 4 },
+ source: 'original.js'
+ });
+ original += ' line ' + i + '\n';
+ }
+ sourceMap.setSourceContent('original.js', original);
+ return sourceMap;
+}
+
+function compareStackTrace(sourceMap, source, expected) {
+ // Check once with a separate source map
+ fs.writeFileSync('.generated.js.map', sourceMap);
+ fs.writeFileSync('.generated.js', 'exports.test = function() {' +
+ source.join('\n') + '};//@ sourceMappingURL=.generated.js.map');
+ try {
+ delete require.cache[require.resolve('./.generated')];
+ require('./.generated').test();
+ } catch (e) {
+ compareLines(e.stack.split(/\r\n|\n/), expected);
+ }
+ fs.unlinkSync('.generated.js');
+ fs.unlinkSync('.generated.js.map');
+
+ // Check again with an inline source map (in a data URL)
+ fs.writeFileSync('.generated.js', 'exports.test = function() {' +
+ source.join('\n') + '};//@ sourceMappingURL=data:application/json;base64,' +
+ new Buffer(sourceMap.toString()).toString('base64'));
+ try {
+ delete require.cache[require.resolve('./.generated')];
+ require('./.generated').test();
+ } catch (e) {
+ compareLines(e.stack.split(/\r\n|\n/), expected);
+ }
+ fs.unlinkSync('.generated.js');
+}
+
+function compareStdout(done, sourceMap, source, expected) {
+ fs.writeFileSync('.original.js', 'this is the original code');
+ fs.writeFileSync('.generated.js.map', sourceMap);
+ fs.writeFileSync('.generated.js', source.join('\n') +
+ '//@ sourceMappingURL=.generated.js.map');
+ child_process.exec('node ./.generated', function(error, stdout, stderr) {
+ try {
+ compareLines(
+ (stdout + stderr)
+ .trim()
+ .split(/\r\n|\n/)
+ .filter(function (line) { return line !== '' }), // Empty lines are not relevant.
+ expected
+ );
+ } catch (e) {
+ return done(e);
+ }
+ fs.unlinkSync('.generated.js');
+ fs.unlinkSync('.generated.js.map');
+ fs.unlinkSync('.original.js');
+ done();
+ });
+}
+
+it('normal throw', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'throw new Error("test");'
+ ], [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ]);
+});
+
+it('throw inside function', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'function foo() {',
+ ' throw new Error("test");',
+ '}',
+ 'foo();'
+ ], [
+ 'Error: test',
+ /^ at foo \((?:.*[/\\])?line2\.js:1002:102\)$/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line4\.js:1004:104\)$/
+ ]);
+});
+
+it('throw inside function inside function', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'function foo() {',
+ ' function bar() {',
+ ' throw new Error("test");',
+ ' }',
+ ' bar();',
+ '}',
+ 'foo();'
+ ], [
+ 'Error: test',
+ /^ at bar \((?:.*[/\\])?line3\.js:1003:103\)$/,
+ /^ at foo \((?:.*[/\\])?line5\.js:1005:105\)$/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line7\.js:1007:107\)$/
+ ]);
+});
+
+it('eval', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'eval("throw new Error(\'test\')");'
+ ], [
+ 'Error: test',
+
+ // Before Node 4, `Object.eval`, after just `eval`.
+ /^ at (?:Object\.)?eval \(eval at (<anonymous>|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/,
+
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ]);
+});
+
+it('eval inside eval', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'eval("eval(\'throw new Error(\\"test\\")\')");'
+ ], [
+ 'Error: test',
+ /^ at (?:Object\.)?eval \(eval at (<anonymous>|exports.test) \(eval at (<anonymous>|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/,
+ /^ at (?:Object\.)?eval \(eval at (<anonymous>|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ]);
+});
+
+it('eval inside function', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'function foo() {',
+ ' eval("throw new Error(\'test\')");',
+ '}',
+ 'foo();'
+ ], [
+ 'Error: test',
+ /^ at eval \(eval at foo \((?:.*[/\\])?line2\.js:1002:102\)/,
+ /^ at foo \((?:.*[/\\])?line2\.js:1002:102\)/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line4\.js:1004:104\)$/
+ ]);
+});
+
+it('eval with sourceURL', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'eval("throw new Error(\'test\')//@ sourceURL=sourceURL.js");'
+ ], [
+ 'Error: test',
+ /^ at (?:Object\.)?eval \(sourceURL\.js:1:7\)$/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ]);
+});
+
+it('eval with sourceURL inside eval', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'eval("eval(\'throw new Error(\\"test\\")//@ sourceURL=sourceURL.js\')");'
+ ], [
+ 'Error: test',
+ /^ at (?:Object\.)?eval \(sourceURL\.js:1:7\)$/,
+ /^ at (?:Object\.)?eval \(eval at (<anonymous>|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/,
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ]);
+});
+
+it('native function', function() {
+ compareStackTrace(createSingleLineSourceMap(), [
+ '[1].map(function(x) { throw new Error(x); });'
+ ], [
+ 'Error: 1',
+ /[/\\].original\.js/,
+ /at Array\.map \(native\)/
+ ]);
+});
+
+it('function constructor', function() {
+ compareStackTrace(createMultiLineSourceMap(), [
+ 'throw new Function(")");'
+ ], [
+ 'SyntaxError: Unexpected token )',
+ ]);
+});
+
+it('throw with empty source map', function() {
+ compareStackTrace(createEmptySourceMap(), [
+ 'throw new Error("test");'
+ ], [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?.generated.js:1:34\)$/
+ ]);
+});
+
+it('throw in Timeout with empty source map', function(done) {
+ compareStdout(done, createEmptySourceMap(), [
+ 'require("./source-map-support").install();',
+ 'setTimeout(function () {',
+ ' throw new Error("this is the error")',
+ '})'
+ ], [
+ /[/\\].generated.js:3$/,
+ ' throw new Error("this is the error")',
+ /^ \^$/,
+ 'Error: this is the error',
+ /^ at ((null)|(Timeout))\._onTimeout \((?:.*[/\\])?.generated.js:3:11\)$/
+ ]);
+});
+
+it('throw with source map with gap', function() {
+ compareStackTrace(createSourceMapWithGap(), [
+ 'throw new Error("test");'
+ ], [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?.generated.js:1:34\)$/
+ ]);
+});
+
+it('sourcesContent with data URL', function() {
+ compareStackTrace(createMultiLineSourceMapWithSourcesContent(), [
+ 'throw new Error("test");'
+ ], [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?original.js:1001:5\)$/
+ ]);
+});
+
+it('finds the last sourceMappingURL', function() {
+ compareStackTrace(createMultiLineSourceMapWithSourcesContent(), [
+ '//# sourceMappingURL=missing.map.js', // NB: compareStackTrace adds another source mapping.
+ 'throw new Error("test");'
+ ], [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?original.js:1002:5\)$/
+ ]);
+});
+
+it('default options', function(done) {
+ compareStdout(done, createSecondLineSourceMap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install();',
+ 'process.nextTick(foo);',
+ 'process.nextTick(function() { process.exit(1); });'
+ ], [
+ /[/\\].original\.js:1$/,
+ 'this is the original code',
+ '^',
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.original\.js:1:1\)$/
+ ]);
+});
+
+it('handleUncaughtExceptions is true', function(done) {
+ compareStdout(done, createSecondLineSourceMap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install({ handleUncaughtExceptions: true });',
+ 'process.nextTick(foo);'
+ ], [
+ /[/\\].original\.js:1$/,
+ 'this is the original code',
+ '^',
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.original\.js:1:1\)$/
+ ]);
+});
+
+it('handleUncaughtExceptions is false', function(done) {
+ compareStdout(done, createSecondLineSourceMap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install({ handleUncaughtExceptions: false });',
+ 'process.nextTick(foo);'
+ ], [
+ /[/\\].generated.js:2$/,
+ 'function foo() { throw new Error("this is the error"); }',
+
+ // Before Node 4, the arrow points on the `new`, after on the
+ // `throw`.
+ /^ (?: )?\^$/,
+
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.original\.js:1:1\)$/
+ ]);
+});
+
+it('default options with empty source map', function(done) {
+ compareStdout(done, createEmptySourceMap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install();',
+ 'process.nextTick(foo);'
+ ], [
+ /[/\\].generated.js:2$/,
+ 'function foo() { throw new Error("this is the error"); }',
+ /^ (?: )?\^$/,
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.generated.js:2:24\)$/
+ ]);
+});
+
+it('default options with source map with gap', function(done) {
+ compareStdout(done, createSourceMapWithGap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install();',
+ 'process.nextTick(foo);'
+ ], [
+ /[/\\].generated.js:2$/,
+ 'function foo() { throw new Error("this is the error"); }',
+ /^ (?: )?\^$/,
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.generated.js:2:24\)$/
+ ]);
+});
+
+it('specifically requested error source', function(done) {
+ compareStdout(done, createSecondLineSourceMap(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'var sms = require("./source-map-support");',
+ 'sms.install({ handleUncaughtExceptions: false });',
+ 'process.on("uncaughtException", function (e) { console.log("SRC:" + sms.getErrorSource(e)); });',
+ 'process.nextTick(foo);'
+ ], [
+ /^SRC:.*[/\\].original.js:1$/,
+ 'this is the original code',
+ '^'
+ ]);
+});
+
+it('sourcesContent', function(done) {
+ compareStdout(done, createMultiLineSourceMapWithSourcesContent(), [
+ '',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install();',
+ 'process.nextTick(foo);',
+ 'process.nextTick(function() { process.exit(1); });'
+ ], [
+ /[/\\]original\.js:1002$/,
+ ' line 2',
+ ' ^',
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?original\.js:1002:5\)$/
+ ]);
+});
+
+it('missing source maps should also be cached', function(done) {
+ compareStdout(done, createSingleLineSourceMap(), [
+ '',
+ 'var count = 0;',
+ 'function foo() {',
+ ' console.log(new Error("this is the error").stack.split("\\n").slice(0, 2).join("\\n"));',
+ '}',
+ 'require("./source-map-support").install({',
+ ' overrideRetrieveSourceMap: true,',
+ ' retrieveSourceMap: function(name) {',
+ ' if (/\\.generated.js$/.test(name)) count++;',
+ ' return null;',
+ ' }',
+ '});',
+ 'process.nextTick(foo);',
+ 'process.nextTick(foo);',
+ 'process.nextTick(function() { console.log(count); });',
+ ], [
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.generated.js:4:15\)$/,
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?.generated.js:4:15\)$/,
+ '1', // The retrieval should only be attempted once
+ ]);
+});
+
+it('should consult all retrieve source map providers', function(done) {
+ compareStdout(done, createSingleLineSourceMap(), [
+ '',
+ 'var count = 0;',
+ 'function foo() {',
+ ' console.log(new Error("this is the error").stack.split("\\n").slice(0, 2).join("\\n"));',
+ '}',
+ 'require("./source-map-support").install({',
+ ' retrieveSourceMap: function(name) {',
+ ' if (/\\.generated.js$/.test(name)) count++;',
+ ' return undefined;',
+ ' }',
+ '});',
+ 'require("./source-map-support").install({',
+ ' retrieveSourceMap: function(name) {',
+ ' if (/\\.generated.js$/.test(name)) {',
+ ' count++;',
+ ' return ' + JSON.stringify({url: '.original.js', map: createMultiLineSourceMapWithSourcesContent().toJSON()}) + ';',
+ ' }',
+ ' }',
+ '});',
+ 'process.nextTick(foo);',
+ 'process.nextTick(foo);',
+ 'process.nextTick(function() { console.log(count); });',
+ ], [
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?original.js:1004:5\)$/,
+ 'Error: this is the error',
+ /^ at foo \((?:.*[/\\])?original.js:1004:5\)$/,
+ '1', // The retrieval should only be attempted once
+ ]);
+});
+
+it('should allow for runtime inline source maps', function(done) {
+ var sourceMap = createMultiLineSourceMapWithSourcesContent();
+
+ fs.writeFileSync('.generated.jss', 'foo');
+
+ compareStdout(function(err) {
+ fs.unlinkSync('.generated.jss');
+ done(err);
+ }, createSingleLineSourceMap(), [
+ 'require("./source-map-support").install({',
+ ' hookRequire: true',
+ '});',
+ 'require.extensions[".jss"] = function(module, filename) {',
+ ' module._compile(',
+ JSON.stringify([
+ '',
+ 'var count = 0;',
+ 'function foo() {',
+ ' console.log(new Error("this is the error").stack.split("\\n").slice(0, 2).join("\\n"));',
+ '}',
+ 'process.nextTick(foo);',
+ 'process.nextTick(foo);',
+ 'process.nextTick(function() { console.log(count); });',
+ '//@ sourceMappingURL=data:application/json;charset=utf8;base64,' + new Buffer(sourceMap.toString()).toString('base64')
+ ].join('\n')),
+ ', filename);',
+ '};',
+ 'require("./.generated.jss");',
+ ], [
+ 'Error: this is the error',
+ /^ at foo \(.*[/\\]original.js:1004:5\)$/,
+ 'Error: this is the error',
+ /^ at foo \(.*[/\\]original.js:1004:5\)$/,
+ '0', // The retrieval should only be attempted once
+ ]);
+});
+
+/* The following test duplicates some of the code in
+ * `compareStackTrace` but appends a charset to the
+ * source mapping url.
+ */
+it('finds source maps with charset specified', function() {
+ var sourceMap = createMultiLineSourceMap()
+ var source = [ 'throw new Error("test");' ];
+ var expected = [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ];
+
+ fs.writeFileSync('.generated.js', 'exports.test = function() {' +
+ source.join('\n') + '};//@ sourceMappingURL=data:application/json;charset=utf8;base64,' +
+ new Buffer(sourceMap.toString()).toString('base64'));
+ try {
+ delete require.cache[require.resolve('./.generated')];
+ require('./.generated').test();
+ } catch (e) {
+ compareLines(e.stack.split(/\r\n|\n/), expected);
+ }
+ fs.unlinkSync('.generated.js');
+});
+
+/* The following test duplicates some of the code in
+ * `compareStackTrace` but appends some code and a
+ * comment to the source mapping url.
+ */
+it('allows code/comments after sourceMappingURL', function() {
+ var sourceMap = createMultiLineSourceMap()
+ var source = [ 'throw new Error("test");' ];
+ var expected = [
+ 'Error: test',
+ /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/
+ ];
+
+ fs.writeFileSync('.generated.js', 'exports.test = function() {' +
+ source.join('\n') + '};//# sourceMappingURL=data:application/json;base64,' +
+ new Buffer(sourceMap.toString()).toString('base64') +
+ '\n// Some comment below the sourceMappingURL\nvar foo = 0;');
+ try {
+ delete require.cache[require.resolve('./.generated')];
+ require('./.generated').test();
+ } catch (e) {
+ compareLines(e.stack.split(/\r\n|\n/), expected);
+ }
+ fs.unlinkSync('.generated.js');
+});
+
+it('handleUncaughtExceptions is true with existing listener', function(done) {
+ var source = [
+ 'process.on("uncaughtException", function() { /* Silent */ });',
+ 'function foo() { throw new Error("this is the error"); }',
+ 'require("./source-map-support").install();',
+ 'process.nextTick(foo);',
+ '//@ sourceMappingURL=.generated.js.map'
+ ];
+
+ fs.writeFileSync('.original.js', 'this is the original code');
+ fs.writeFileSync('.generated.js.map', createSingleLineSourceMap());
+ fs.writeFileSync('.generated.js', source.join('\n'));
+
+ child_process.exec('node ./.generated', function(error, stdout, stderr) {
+ fs.unlinkSync('.generated.js');
+ fs.unlinkSync('.generated.js.map');
+ fs.unlinkSync('.original.js');
+ assert.equal((stdout + stderr).trim(), '');
+ done();
+ });
+});