diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 92cc7bc..5274c81 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -18,6 +18,8 @@ jobs: matrix: os: [ubuntu, windows] node: + - 18 + - 17 - 16 - 14 - 12 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2a96219 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "Debug Mocha tests", + "type": "node", + "request": "launch", + "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/_mocha", + "runtimeArgs": ["--timeout", "999999999"], + "outputCapture": "std", + "skipFiles": [ + "/**/*.js" + ], + } + ], +} diff --git a/browser-source-map-support.js b/browser-source-map-support.js index 37ac188..782da50 100644 --- a/browser-source-map-support.js +++ b/browser-source-map-support.js @@ -8,107 +8,107 @@ @author Feross Aboukhadijeh license MIT */ -(this.define||function(G,J){this.sourceMapSupport=J()})("browser-source-map-support",function(G){(function b(n,x,m){function e(d,a){if(!x[d]){if(!n[d]){var l="function"==typeof require&&require;if(!a&&l)return l(d,!0);if(g)return g(d,!0);throw Error("Cannot find module '"+d+"'");}l=x[d]={exports:{}};n[d][0].call(l.exports,function(a){var b=n[d][1][a];return e(b?b:a)},l,l.exports,b,n,x,m)}return x[d].exports}for(var g="function"==typeof require&&require,h=0;hb)return-1;if(58>b)return b-48+52;if(91>b)return b-65;if(123>b)return b-97+26}var g="undefined"!==typeof Uint8Array?Uint8Array:Array;b.toByteArray=function(b){function d(a){r[v++]=a}if(0>16);d((h&65280)>>8);d(h&255)}2===l?(h=e(b.charAt(a))<<2|e(b.charAt(a+1))>>4,d(h&255)):1===l&&(h=e(b.charAt(a))<<10|e(b.charAt(a+1))<<4|e(b.charAt(a+2))>>2,d(h>>8&255),d(h&255));return r};b.fromByteArray=function(b){var d=b.length%3,a="",l;var e=0;for(l=b.length-d;e> -18&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g>>12&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g>>6&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g&63);a+=g}switch(d){case 1:g=b[b.length-1];a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g>>2);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g<<4&63);a+="==";break;case 2:g=(b[b.length-2]<<8)+ -b[b.length-1],a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g>>10),a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g>>4&63),a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g<<2&63),a+="="}return a}})("undefined"===typeof m?this.base64js={}:m)},{}],3:[function(n,x,m){},{}],4:[function(n,x,m){(function(b){var e=Object.prototype.toString,g="function"===typeof b.alloc&&"function"===typeof b.allocUnsafe&&"function"=== -typeof b.from;x.exports=function(h,d,a){if("number"===typeof h)throw new TypeError('"value" argument must not be a number');if("ArrayBuffer"===e.call(h).slice(8,-1)){d>>>=0;var l=h.byteLength-d;if(0>l)throw new RangeError("'offset' is out of bounds");if(void 0===a)a=l;else if(a>>>=0,a>l)throw new RangeError("'length' is out of bounds");return g?b.from(h.slice(d,d+a)):new b(new Uint8Array(h.slice(d,d+a)))}if("string"===typeof h){a=d;if("string"!==typeof a||""===a)a="utf8";if(!b.isEncoding(a))throw new TypeError('"encoding" must be a valid string encoding'); -return g?b.from(h,a):new b(h,a)}return g?b.from(h):new b(h)}}).call(this,n("buffer").Buffer)},{buffer:5}],5:[function(n,x,m){function b(f,p,a){if(!(this instanceof b))return new b(f,p,a);var c=typeof f;if("number"===c)var d=0>>0:0;else if("string"===c){if("base64"===p)for(f=(f.trim?f.trim():f.replace(/^\s+|\s+$/g,"")).replace(H,"");0!==f.length%4;)f+="=";d=b.byteLength(f,p)}else if("object"===c&&null!==f)"Buffer"===f.type&&F(f.data)&&(f=f.data),d=0<+f.length?Math.floor(+f.length):0;else throw new TypeError("must start with number, buffer, array or string"); -if(this.length>D)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+D.toString(16)+" bytes");if(b.TYPED_ARRAY_SUPPORT)var k=b._augment(new Uint8Array(d));else k=this,k.length=d,k._isBuffer=!0;if(b.TYPED_ARRAY_SUPPORT&&"number"===typeof f.byteLength)k._set(f);else{var C=f;if(F(C)||b.isBuffer(C)||C&&"object"===typeof C&&"number"===typeof C.length)if(b.isBuffer(f))for(p=0;pf)throw new RangeError("offset is not uint");if(f+p>b)throw new RangeError("Trying to access beyond buffer length");}function h(f,p,a,c,d,k){if(!b.isBuffer(f))throw new TypeError("buffer must be a Buffer instance");if(p>d||pf.length)throw new TypeError("index out of range"); -}function d(f,p,b,a){0>p&&(p=65535+p+1);for(var c=0,d=Math.min(f.length-b,2);c>>8*(a?c:1-c)}function a(f,p,b,a){0>p&&(p=4294967295+p+1);for(var c=0,d=Math.min(f.length-b,4);c>>8*(a?c:3-c)&255}function l(f,p,b,a,c,d){if(p>c||pf.length)throw new TypeError("index out of range");}function r(f,p,b,a,c){c||l(f,p,b,4,3.4028234663852886E38,-3.4028234663852886E38);y.write(f,p,b,a,23,4);return b+4}function q(f, -p,b,a,c){c||l(f,p,b,8,1.7976931348623157E308,-1.7976931348623157E308);y.write(f,p,b,a,52,8);return b+8}function v(f){for(var p=[],b=0;b=a)p.push(a);else{var c=b;55296<=a&&57343>=a&&b++;a=encodeURIComponent(f.slice(c,b+1)).substr(1).split("%");for(c=0;c=b.length||d>=f.length);d++)b[d+ -a]=f[d];return d}function k(f){try{return decodeURIComponent(f)}catch(p){return String.fromCharCode(65533)}}var w=n("base64-js"),y=n("ieee754"),F=n("is-array");m.Buffer=b;m.SlowBuffer=b;m.INSPECT_MAX_BYTES=50;b.poolSize=8192;var D=1073741823;b.TYPED_ARRAY_SUPPORT=function(){try{var f=new ArrayBuffer(0),b=new Uint8Array(f);b.foo=function(){return 42};return 42===b.foo()&&"function"===typeof b.subarray&&0===(new Uint8Array(1)).subarray(1,1).byteLength}catch(C){return!1}}();b.isBuffer=function(f){return!(null== -f||!f._isBuffer)};b.compare=function(f,a){if(!b.isBuffer(f)||!b.isBuffer(a))throw new TypeError("Arguments must be Buffers");for(var c=f.length,p=a.length,d=0,k=Math.min(c,p);d>>1;break;case "utf8":case "utf-8":b=v(f).length;break;case "base64":b=w.toByteArray(f).length; -break;default:b=f.length}return b};b.prototype.length=void 0;b.prototype.parent=void 0;b.prototype.toString=function(f,b,a){var c=!1;b>>>=0;a=void 0===a||Infinity===a?this.length:a>>>0;f||(f="utf8");0>b&&(b=0);a>this.length&&(a=this.length);if(a<=b)return"";for(;;)switch(f){case "hex":f=b;b=a;a=this.length;if(!f||0>f)f=0;if(!b||0>b||b>a)b=a;c="";for(a=f;ac?"0"+c.toString(16):c.toString(16),c=f+c;return c;case "utf8":case "utf-8":c=f="";for(a=Math.min(this.length,a);b= -this[b]?(f+=k(c)+String.fromCharCode(this[b]),c=""):c+="%"+this[b].toString(16);return f+k(c);case "ascii":return e(this,b,a);case "binary":return e(this,b,a);case "base64":return b=0===b&&a===this.length?w.fromByteArray(this):w.fromByteArray(this.slice(b,a)),b;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":b=this.slice(b,a);a="";for(f=0;fb&&(f+=" ... "));return""};b.prototype.compare=function(f){if(!b.isBuffer(f))throw new TypeError("Argument must be a Buffer");return b.compare(this,f)};b.prototype.get=function(f){console.log(".get() is deprecated. Access using array indexes instead."); -return this.readUInt8(f)};b.prototype.set=function(f,b){console.log(".set() is deprecated. Access using array indexes instead.");return this.writeUInt8(f,b)};b.prototype.write=function(f,b,a,d){if(isFinite(b))isFinite(a)||(d=a,a=void 0);else{var p=d;d=b;b=a;a=p}b=Number(b)||0;p=this.length-b;a?(a=Number(a),a>p&&(a=p)):a=p;d=String(d||"utf8").toLowerCase();switch(d){case "hex":b=Number(b)||0;d=this.length-b;a?(a=Number(a),a>d&&(a=d)):a=d;d=f.length;if(0!==d%2)throw Error("Invalid hex string");a>d/ -2&&(a=d/2);for(d=0;d>8;l%=256;p.push(l);p.push(d)}f=c(p,this,b,a,2);break;default:throw new TypeError("Unknown encoding: "+ -d);}return f};b.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};b.prototype.slice=function(f,a){var c=this.length;f=~~f;a=void 0===a?c:~~a;0>f?(f+=c,0>f&&(f=0)):f>c&&(f=c);0>a?(a+=c,0>a&&(a=0)):a>c&&(a=c);a>>=0;d||h(this,a,c,1,255,0);b.TYPED_ARRAY_SUPPORT||(a=Math.floor(a));this[c]=a;return c+1};b.prototype.writeUInt16LE=function(a, -c,k){a=+a;c>>>=0;k||h(this,a,c,2,65535,0);b.TYPED_ARRAY_SUPPORT?(this[c]=a,this[c+1]=a>>>8):d(this,a,c,!0);return c+2};b.prototype.writeUInt16BE=function(a,c,k){a=+a;c>>>=0;k||h(this,a,c,2,65535,0);b.TYPED_ARRAY_SUPPORT?(this[c]=a>>>8,this[c+1]=a):d(this,a,c,!1);return c+2};b.prototype.writeUInt32LE=function(f,c,d){f=+f;c>>>=0;d||h(this,f,c,4,4294967295,0);b.TYPED_ARRAY_SUPPORT?(this[c+3]=f>>>24,this[c+2]=f>>>16,this[c+1]=f>>>8,this[c]=f):a(this,f,c,!0);return c+4};b.prototype.writeUInt32BE=function(f, -c,d){f=+f;c>>>=0;d||h(this,f,c,4,4294967295,0);b.TYPED_ARRAY_SUPPORT?(this[c]=f>>>24,this[c+1]=f>>>16,this[c+2]=f>>>8,this[c+3]=f):a(this,f,c,!1);return c+4};b.prototype.writeInt8=function(a,c,d){a=+a;c>>>=0;d||h(this,a,c,1,127,-128);b.TYPED_ARRAY_SUPPORT||(a=Math.floor(a));0>a&&(a=255+a+1);this[c]=a;return c+1};b.prototype.writeInt16LE=function(a,c,k){a=+a;c>>>=0;k||h(this,a,c,2,32767,-32768);b.TYPED_ARRAY_SUPPORT?(this[c]=a,this[c+1]=a>>>8):d(this,a,c,!0);return c+2};b.prototype.writeInt16BE=function(a, -c,k){a=+a;c>>>=0;k||h(this,a,c,2,32767,-32768);b.TYPED_ARRAY_SUPPORT?(this[c]=a>>>8,this[c+1]=a):d(this,a,c,!1);return c+2};b.prototype.writeInt32LE=function(c,d,k){c=+c;d>>>=0;k||h(this,c,d,4,2147483647,-2147483648);b.TYPED_ARRAY_SUPPORT?(this[d]=c,this[d+1]=c>>>8,this[d+2]=c>>>16,this[d+3]=c>>>24):a(this,c,d,!0);return d+4};b.prototype.writeInt32BE=function(c,d,k){c=+c;d>>>=0;k||h(this,c,d,4,2147483647,-2147483648);0>c&&(c=4294967295+c+1);b.TYPED_ARRAY_SUPPORT?(this[d]=c>>>24,this[d+1]=c>>>16,this[d+ -2]=c>>>8,this[d+3]=c):a(this,c,d,!1);return d+4};b.prototype.writeFloatLE=function(a,c,b){return r(this,a,c,!0,b)};b.prototype.writeFloatBE=function(a,c,b){return r(this,a,c,!1,b)};b.prototype.writeDoubleLE=function(a,c,b){return q(this,a,c,!0,b)};b.prototype.writeDoubleBE=function(a,c,b){return q(this,a,c,!1,b)};b.prototype.copy=function(a,c,d,k){d||(d=0);k||0===k||(k=this.length);c||(c=0);if(k!==d&&0!==a.length&&0!==this.length){if(kc||c>=a.length)throw new TypeError("targetStart out of bounds"); -if(0>d||d>=this.length)throw new TypeError("sourceStart out of bounds");if(0>k||k>this.length)throw new TypeError("sourceEnd out of bounds");k>this.length&&(k=this.length);a.length-ck||!b.TYPED_ARRAY_SUPPORT)for(var f=0;fc||c>=this.length)throw new TypeError("start out of bounds"); -if(0>b||b>this.length)throw new TypeError("end out of bounds");if("number"===typeof a)for(;c>1,q=-7;d=g?d-1:0;var v=g?-1:1,u=b[e+d];d+=v;g=u&(1<<-q)-1;u>>=-q;for(q+=a;0>=-q;for(q+=h;0>1,u=23===d?Math.pow(2,-24)-Math.pow(2,-77):0;a=h?0:a-1;var c=h?1:-1,k=0>e||0===e&&0>1/e?1:0;e=Math.abs(e);isNaN(e)||Infinity===e?(e=isNaN(e)?1:0,h=q):(h=Math.floor(Math.log(e)/Math.LN2),1>e*(l=Math.pow(2,-h))&&(h--,l*=2),e=1<=h+v?e+u/l:e+u*Math.pow(2,1-v),2<=e*l&&(h++,l/=2),h+v>=q?(e=0,h=q):1<=h+v?(e=(e*l-1)*Math.pow(2,d),h+=v):(e=e*Math.pow(2,v-1)*Math.pow(2,d),h=0));for(;8<=d;b[g+a]=e&255,a+= -c,e/=256,d-=8);h=h<b?[]:a.slice(c,b-c+1)}a=m.resolve(a).substr(1);b=m.resolve(b).substr(1); -for(var l=d(a.split("/")),v=d(b.split("/")),e=Math.min(l.length,v.length),c=e,k=0;kb&&(b=a.length+b);return a.substr(b,d)}}).call(this,n("g5I+bs"))},{"g5I+bs":9}],9:[function(n,x,m){function b(){}n=x.exports={};n.nextTick=function(){if("undefined"!==typeof window&&window.setImmediate)return function(b){return window.setImmediate(b)};if("undefined"!==typeof window&&window.postMessage&&window.addEventListener){var b=[];window.addEventListener("message",function(e){var g=e.source;g!==window&&null!== -g||"process-tick"!==e.data||(e.stopPropagation(),0e?(-e<<1)+1:e<<1;do e=h&31,h>>>=5,0=d)throw Error("Expected more digits in base 64 VLQ value.");var r=b.decode(e.charCodeAt(g++));if(-1===r)throw Error("Invalid base64 digit: "+e.charAt(g-1));var q=!!(r&32);r&=31;a+=r<>1;h.value=1===(a&1)?-e:e;h.rest=g}},{"./base64":12}],12:[function(n, -x,m){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");m.encode=function(e){if(0<=e&&e=b?b-65:97<=b&&122>=b?b-97+26:48<=b&&57>=b?b-48+52:43==b?62:47==b?63:-1}},{}],13:[function(n,x,m){function b(e,g,h,d,a,l){var r=Math.floor((g-e)/2)+e,q=a(h,d[r],!0);return 0===q?r:0e?-1:e}m.GREATEST_LOWER_BOUND=1;m.LEAST_UPPER_BOUND=2;m.search=function(e,g,h,d){if(0===g.length)return-1;e=b(-1,g.length,e,g,h,d||m.GREATEST_LOWER_BOUND);if(0>e)return-1;for(;0<=e-1&&0===h(g[e],g[e-1],!0);)--e;return e}},{}],14:[function(n,x,m){function b(){this._array=[];this._sorted=!0;this._last={generatedLine:-1,generatedColumn:0}}var e=n("./util");b.prototype.unsortedForEach=function(b,e){this._array.forEach(b,e)};b.prototype.add=function(b){var g=this._last,d=g.generatedLine, -a=b.generatedLine,l=g.generatedColumn,r=b.generatedColumn;a>d||a==d&&r>=l||0>=e.compareByGeneratedPositionsInflated(g,b)?this._last=b:this._sorted=!1;this._array.push(b)};b.prototype.toArray=function(){this._sorted||(this._array.sort(e.compareByGeneratedPositionsInflated),this._sorted=!0);return this._array};m.MappingList=b},{"./util":19}],15:[function(n,x,m){function b(b,e,d){var a=b[e];b[e]=b[d];b[d]=a}function e(g,h,d,a){if(d=h(g[q],r)&&(l+=1,b(g,l,q));b(g,l+1,q);l+=1;e(g,h,d,l-1);e(g,h,l+1,a)}}m.quickSort=function(b,h){e(b,h,0,b.length-1)}},{}],16:[function(n,x,m){function b(a,b){var c=a;"string"===typeof a&&(c=d.parseSourceMapInput(a));return null!=c.sections?new h(c,b):new e(c,b)}function e(a,b){var c=a;"string"===typeof a&&(c=d.parseSourceMapInput(a));var k=d.getArg(c,"version"),e=d.getArg(c,"sources"),v=d.getArg(c,"names",[]),g=d.getArg(c,"sourceRoot",null),h=d.getArg(c,"sourcesContent",null),q=d.getArg(c, -"mappings");c=d.getArg(c,"file",null);if(k!=this._version)throw Error("Unsupported version: "+k);g&&(g=d.normalize(g));e=e.map(String).map(d.normalize).map(function(a){return g&&d.isAbsolute(g)&&d.isAbsolute(a)?d.relative(g,a):a});this._names=l.fromArray(v.map(String),!0);this._sources=l.fromArray(e,!0);this.sourceRoot=g;this.sourcesContent=h;this._mappings=q;this._sourceMapURL=b;this.file=c}function g(){this.generatedColumn=this.generatedLine=0;this.name=this.originalColumn=this.originalLine=this.source= -null}function h(a,e){var c=a;"string"===typeof a&&(c=d.parseSourceMapInput(a));var k=d.getArg(c,"version");c=d.getArg(c,"sections");if(k!=this._version)throw Error("Unsupported version: "+k);this._sources=new l;this._names=new l;var v={line:-1,column:0};this._sections=c.map(function(a){if(a.url)throw Error("Support for url field in sections not implemented.");var c=d.getArg(a,"offset"),k=d.getArg(c,"line"),g=d.getArg(c,"column");if(k=b[c])throw new TypeError("Line must be greater than or equal to 1, got "+ -b[c]);if(0>b[k])throw new TypeError("Column must be greater than or equal to 0, got "+b[k]);return a.search(b,d,e,g)};e.prototype.computeColumnSpans=function(){for(var a=0;a=this._sources.size()&&!this.sourcesContent.some(function(a){return null==a}):!1};e.prototype.sourceContentFor=function(a,b){if(!this.sourcesContent)return null;var c=a;null!=this.sourceRoot&&(c=d.relative(this.sourceRoot,c));if(this._sources.has(c))return this.sourcesContent[this._sources.indexOf(c)]; -var k=this.sources,e;for(e=0;e -b||95!==a.charCodeAt(b-1)||95!==a.charCodeAt(b-2)||111!==a.charCodeAt(b-3)||116!==a.charCodeAt(b-4)||111!==a.charCodeAt(b-5)||114!==a.charCodeAt(b-6)||112!==a.charCodeAt(b-7)||95!==a.charCodeAt(b-8)||95!==a.charCodeAt(b-9))return!1;for(b-=10;0<=b;b--)if(36!==a.charCodeAt(b))return!1;return!0}function q(a,b){return a===b?0:null===a?1:null===b?-1:a>b?1:-1}m.getArg=function(a,b,d){if(b in a)return a[b];if(3===arguments.length)return d;throw Error('"'+b+'" is a required argument.');};var v=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/, -u=/^data:.+,.+$/;m.urlParse=b;m.urlGenerate=e;m.normalize=g;m.join=h;m.isAbsolute=function(a){return"/"===a.charAt(0)||v.test(a)};m.relative=function(a,b){""===a&&(a=".");a=a.replace(/\/$/,"");for(var c=0;0!==b.indexOf(a+"/");){var d=a.lastIndexOf("/");if(0>d)return b;a=a.slice(0,d);if(a.match(/^([^\/]+:\/)?\/*$/))return b;++c}return Array(c+1).join("../")+b.substr(a.length+1)};n=!("__proto__"in Object.create(null));m.toSetString=n?d:a;m.fromSetString=n?d:l;m.compareByOriginalPositions=function(a, -b,d){var c=q(a.source,b.source);if(0!==c)return c;c=a.originalLine-b.originalLine;if(0!==c)return c;c=a.originalColumn-b.originalColumn;if(0!==c||d)return c;c=a.generatedColumn-b.generatedColumn;if(0!==c)return c;c=a.generatedLine-b.generatedLine;return 0!==c?c:q(a.name,b.name)};m.compareByGeneratedPositionsDeflated=function(a,b,d){var c=a.generatedLine-b.generatedLine;if(0!==c)return c;c=a.generatedColumn-b.generatedColumn;if(0!==c||d)return c;c=q(a.source,b.source);if(0!==c)return c;c=a.originalLine- -b.originalLine;if(0!==c)return c;c=a.originalColumn-b.originalColumn;return 0!==c?c:q(a.name,b.name)};m.compareByGeneratedPositionsInflated=function(a,b){var c=a.generatedLine-b.generatedLine;if(0!==c)return c;c=a.generatedColumn-b.generatedColumn;if(0!==c)return c;c=q(a.source,b.source);if(0!==c)return c;c=a.originalLine-b.originalLine;if(0!==c)return c;c=a.originalColumn-b.originalColumn;return 0!==c?c:q(a.name,b.name)};m.parseSourceMapInput=function(a){return JSON.parse(a.replace(/^\)]}'[^\n]*\n/, -""))};m.computeSourceURL=function(a,d,l){d=d||"";a&&("/"!==a[a.length-1]&&"/"!==d[0]&&(a+="/"),d=a+d);if(l){a=b(l);if(!a)throw Error("sourceMapURL could not be parsed");a.path&&(l=a.path.lastIndexOf("/"),0<=l&&(a.path=a.path.substring(0,l+1)));d=h(e(a),d)}return g(d)}},{}],20:[function(n,x,m){m.SourceMapGenerator=n("./lib/source-map-generator").SourceMapGenerator;m.SourceMapConsumer=n("./lib/source-map-consumer").SourceMapConsumer;m.SourceNode=n("./lib/source-node").SourceNode},{"./lib/source-map-consumer":16, -"./lib/source-map-generator":17,"./lib/source-node":18}],21:[function(n,x,m){(function(b){function e(){return"browser"===f?!0:"node"===f?!1:"undefined"!==typeof window&&"function"===typeof XMLHttpRequest&&!(window.require&&window.module&&window.process&&"renderer"===window.process.type)}function g(a){return function(b){for(var c=0;c";b=this.getLineNumber();null!=b&&(a+=":"+b,(b= -this.getColumnNumber())&&(a+=":"+b))}b="";var c=this.getFunctionName(),d=!0,e=this.isConstructor();if(this.isToplevel()||e)e?b+="new "+(c||""):c?b+=c:(b+=a,d=!1);else{e=this.getTypeName();"[object Object]"===e&&(e="null");var f=this.getMethodName();c?(e&&0!=c.indexOf(e)&&(b+=e+"."),b+=c,f&&c.indexOf("."+f)!=c.length-f.length-1&&(b+=" [as "+f+"]")):b+=e+"."+(f||"")}d&&(b+=" ("+a+")");return b}function r(a){var b={};Object.getOwnPropertyNames(Object.getPrototypeOf(a)).forEach(function(c){b[c]= -/^(?:is|get)/.test(c)?function(){return a[c].call(a)}:a[c]});b.toString=l;return b}function q(c,f){void 0===f&&(f={nextPosition:null,curPosition:null});if(c.isNative())return f.curPosition=null,c;var g=c.getFileName()||c.getScriptNameOrSourceURL();if(g){var h=c.getLineNumber(),k=c.getColumnNumber()-1,l=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/.test(b.version)?0:62;1===h&&k>l&&!e()&&!c.isEval()&&(k-=l);var m=d({source:g,line:h,column:k});f.curPosition=m;c=r(c);var p= -c.getFunctionName;c.getFunctionName=function(){return null==f.nextPosition?p():f.nextPosition.name||p()};c.getFileName=function(){return m.source};c.getLineNumber=function(){return m.line};c.getColumnNumber=function(){return m.column+1};c.getScriptNameOrSourceURL=function(){return m.source};return c}var n=c.isEval()&&c.getEvalOrigin();n&&(n=a(n),c=r(c),c.getEvalOrigin=function(){return n});return c}function v(a,b){H&&(p={},C={});for(var c=(a.name||"Error")+": "+(a.message||""),d={nextPosition:null, -curPosition:null},e=[],f=b.length-1;0<=f;f--)e.push("\n at "+q(b[f],d)),d.nextPosition=d.curPosition;d.curPosition=d.nextPosition=null;return c+e.reverse().join("")}function u(a){var b=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(a.stack);if(b){a=b[1];var c=+b[2];b=+b[3];var d=p[a];if(!d&&y&&y.existsSync(a))try{d=y.readFileSync(a,"utf8")}catch(N){d=""}if(d&&(d=d.split(/(?:\r\n|\r|\n)/)[c-1]))return a+":"+c+"\n"+d+"\n"+Array(b).join(" ")+"^"}return null}function c(){var a=b.emit;b.emit=function(c){if("uncaughtException"=== -c){var d=arguments[1]&&arguments[1].stack,e=0m)return-1;if(58>m)return m-48+52;if(91>m)return m-65;if(123>m)return m-97+26}var t="undefined"!==typeof Uint8Array?Uint8Array:Array;e.toByteArray=function(m){function f(d){q[k++]=d}if(0>16);f((u&65280)>>8);f(u&255)}2===l?(u=p(m.charAt(c))<<2|p(m.charAt(c+1))>>4,f(u&255)):1===l&&(u=p(m.charAt(c))<<10|p(m.charAt(c+1))<<4|p(m.charAt(c+2))>>2,f(u>>8&255),f(u&255));return q};e.fromByteArray=function(m){var f=m.length%3,c="",l;var q=0;for(l=m.length-f;q> +18&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r>>12&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r>>6&63)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r&63);c+=r}switch(f){case 1:r=m[m.length-1];c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r>>2);c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r<<4&63);c+="==";break;case 2:r=(m[m.length-2]<<8)+ +m[m.length-1],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r>>10),c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r>>4&63),c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(r<<2&63),c+="="}return c}})("undefined"===typeof A?this.base64js={}:A)},{}],3:[function(C,J,A){},{}],4:[function(C,J,A){(function(e){var p=Object.prototype.toString,t="function"===typeof e.alloc&&"function"===typeof e.allocUnsafe&&"function"=== +typeof e.from;J.exports=function(m,f,c){if("number"===typeof m)throw new TypeError('"value" argument must not be a number');if("ArrayBuffer"===p.call(m).slice(8,-1)){f>>>=0;var l=m.byteLength-f;if(0>l)throw new RangeError("'offset' is out of bounds");if(void 0===c)c=l;else if(c>>>=0,c>l)throw new RangeError("'length' is out of bounds");return t?e.from(m.slice(f,f+c)):new e(new Uint8Array(m.slice(f,f+c)))}if("string"===typeof m){c=f;if("string"!==typeof c||""===c)c="utf8";if(!e.isEncoding(c))throw new TypeError('"encoding" must be a valid string encoding'); +return t?e.from(m,c):new e(m,c)}return t?e.from(m):new e(m)}}).call(this,C("buffer").Buffer)},{buffer:5}],5:[function(C,J,A){function e(a,b,h){if(!(this instanceof e))return new e(a,b,h);var w=typeof a;if("number"===w)var y=0>>0:0;else if("string"===w){if("base64"===b)for(a=(a.trim?a.trim():a.replace(/^\s+|\s+$/g,"")).replace(L,"");0!==a.length%4;)a+="=";y=e.byteLength(a,b)}else if("object"===w&&null!==a)"Buffer"===a.type&&z(a.data)&&(a=a.data),y=0<+a.length?Math.floor(+a.length):0;else throw new TypeError("must start with number, buffer, array or string"); +if(this.length>G)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+G.toString(16)+" bytes");if(e.TYPED_ARRAY_SUPPORT)var I=e._augment(new Uint8Array(y));else I=this,I.length=y,I._isBuffer=!0;if(e.TYPED_ARRAY_SUPPORT&&"number"===typeof a.byteLength)I._set(a);else{var K=a;if(z(K)||e.isBuffer(K)||K&&"object"===typeof K&&"number"===typeof K.length)if(e.isBuffer(a))for(b=0;ba)throw new RangeError("offset is not uint");if(a+b>h)throw new RangeError("Trying to access beyond buffer length");}function m(a,b,h,w,y,I){if(!e.isBuffer(a))throw new TypeError("buffer must be a Buffer instance");if(b>y||ba.length)throw new TypeError("index out of range"); +}function f(a,b,h,w){0>b&&(b=65535+b+1);for(var y=0,I=Math.min(a.length-h,2);y>>8*(w?y:1-y)}function c(a,b,h,w){0>b&&(b=4294967295+b+1);for(var y=0,I=Math.min(a.length-h,4);y>>8*(w?y:3-y)&255}function l(a,b,h,w,y,I){if(b>y||ba.length)throw new TypeError("index out of range");}function q(a,b,h,w,y){y||l(a,b,h,4,3.4028234663852886E38,-3.4028234663852886E38);v.write(a,b,h,w,23,4);return h+4}function r(a, +b,h,w,y){y||l(a,b,h,8,1.7976931348623157E308,-1.7976931348623157E308);v.write(a,b,h,w,52,8);return h+8}function k(a){for(var b=[],h=0;h=w)b.push(w);else{var y=h;55296<=w&&57343>=w&&h++;w=encodeURIComponent(a.slice(y,h+1)).substr(1).split("%");for(y=0;y=b.length||y>=a.length);y++)b[y+ +h]=a[y];return y}function g(a){try{return decodeURIComponent(a)}catch(b){return String.fromCharCode(65533)}}var n=C("base64-js"),v=C("ieee754"),z=C("is-array");A.Buffer=e;A.SlowBuffer=e;A.INSPECT_MAX_BYTES=50;e.poolSize=8192;var G=1073741823;e.TYPED_ARRAY_SUPPORT=function(){try{var a=new ArrayBuffer(0),b=new Uint8Array(a);b.foo=function(){return 42};return 42===b.foo()&&"function"===typeof b.subarray&&0===(new Uint8Array(1)).subarray(1,1).byteLength}catch(h){return!1}}();e.isBuffer=function(a){return!(null== +a||!a._isBuffer)};e.compare=function(a,b){if(!e.isBuffer(a)||!e.isBuffer(b))throw new TypeError("Arguments must be Buffers");for(var h=a.length,w=b.length,y=0,I=Math.min(h,w);y>>1;break;case "utf8":case "utf-8":h=k(a).length;break;case "base64":h=n.toByteArray(a).length; +break;default:h=a.length}return h};e.prototype.length=void 0;e.prototype.parent=void 0;e.prototype.toString=function(a,b,h){var w=!1;b>>>=0;h=void 0===h||Infinity===h?this.length:h>>>0;a||(a="utf8");0>b&&(b=0);h>this.length&&(h=this.length);if(h<=b)return"";for(;;)switch(a){case "hex":a=b;b=h;h=this.length;if(!a||0>a)a=0;if(!b||0>b||b>h)b=h;w="";for(h=a;hw?"0"+w.toString(16):w.toString(16),w=a+w;return w;case "utf8":case "utf-8":w=a="";for(h=Math.min(this.length,h);b= +this[b]?(a+=g(w)+String.fromCharCode(this[b]),w=""):w+="%"+this[b].toString(16);return a+g(w);case "ascii":return p(this,b,h);case "binary":return p(this,b,h);case "base64":return b=0===b&&h===this.length?n.fromByteArray(this):n.fromByteArray(this.slice(b,h)),b;case "ucs2":case "ucs-2":case "utf16le":case "utf-16le":b=this.slice(b,h);h="";for(a=0;ab&&(a+=" ... "));return""};e.prototype.compare=function(a){if(!e.isBuffer(a))throw new TypeError("Argument must be a Buffer");return e.compare(this,a)};e.prototype.get=function(a){console.log(".get() is deprecated. Access using array indexes instead."); +return this.readUInt8(a)};e.prototype.set=function(a,b){console.log(".set() is deprecated. Access using array indexes instead.");return this.writeUInt8(a,b)};e.prototype.write=function(a,b,h,w){if(isFinite(b))isFinite(h)||(w=h,h=void 0);else{var y=w;w=b;b=h;h=y}b=Number(b)||0;y=this.length-b;h?(h=Number(h),h>y&&(h=y)):h=y;w=String(w||"utf8").toLowerCase();switch(w){case "hex":b=Number(b)||0;w=this.length-b;h?(h=Number(h),h>w&&(h=w)):h=w;w=a.length;if(0!==w%2)throw Error("Invalid hex string");h>w/ +2&&(h=w/2);for(w=0;w>8;K%=256;y.push(K);y.push(w)}a=d(y,this,b,h,2);break;default:throw new TypeError("Unknown encoding: "+ +w);}return a};e.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};e.prototype.slice=function(a,b){var h=this.length;a=~~a;b=void 0===b?h:~~b;0>a?(a+=h,0>a&&(a=0)):a>h&&(a=h);0>b?(b+=h,0>b&&(b=0)):b>h&&(b=h);b>>=0;h||m(this,a,b,1,255,0);e.TYPED_ARRAY_SUPPORT||(a=Math.floor(a));this[b]=a;return b+1};e.prototype.writeUInt16LE=function(a, +b,h){a=+a;b>>>=0;h||m(this,a,b,2,65535,0);e.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8):f(this,a,b,!0);return b+2};e.prototype.writeUInt16BE=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,2,65535,0);e.TYPED_ARRAY_SUPPORT?(this[b]=a>>>8,this[b+1]=a):f(this,a,b,!1);return b+2};e.prototype.writeUInt32LE=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,4,4294967295,0);e.TYPED_ARRAY_SUPPORT?(this[b+3]=a>>>24,this[b+2]=a>>>16,this[b+1]=a>>>8,this[b]=a):c(this,a,b,!0);return b+4};e.prototype.writeUInt32BE=function(a, +b,h){a=+a;b>>>=0;h||m(this,a,b,4,4294967295,0);e.TYPED_ARRAY_SUPPORT?(this[b]=a>>>24,this[b+1]=a>>>16,this[b+2]=a>>>8,this[b+3]=a):c(this,a,b,!1);return b+4};e.prototype.writeInt8=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,1,127,-128);e.TYPED_ARRAY_SUPPORT||(a=Math.floor(a));0>a&&(a=255+a+1);this[b]=a;return b+1};e.prototype.writeInt16LE=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,2,32767,-32768);e.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8):f(this,a,b,!0);return b+2};e.prototype.writeInt16BE=function(a, +b,h){a=+a;b>>>=0;h||m(this,a,b,2,32767,-32768);e.TYPED_ARRAY_SUPPORT?(this[b]=a>>>8,this[b+1]=a):f(this,a,b,!1);return b+2};e.prototype.writeInt32LE=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,4,2147483647,-2147483648);e.TYPED_ARRAY_SUPPORT?(this[b]=a,this[b+1]=a>>>8,this[b+2]=a>>>16,this[b+3]=a>>>24):c(this,a,b,!0);return b+4};e.prototype.writeInt32BE=function(a,b,h){a=+a;b>>>=0;h||m(this,a,b,4,2147483647,-2147483648);0>a&&(a=4294967295+a+1);e.TYPED_ARRAY_SUPPORT?(this[b]=a>>>24,this[b+1]=a>>>16,this[b+ +2]=a>>>8,this[b+3]=a):c(this,a,b,!1);return b+4};e.prototype.writeFloatLE=function(a,b,h){return q(this,a,b,!0,h)};e.prototype.writeFloatBE=function(a,b,h){return q(this,a,b,!1,h)};e.prototype.writeDoubleLE=function(a,b,h){return r(this,a,b,!0,h)};e.prototype.writeDoubleBE=function(a,b,h){return r(this,a,b,!1,h)};e.prototype.copy=function(a,b,h,w){h||(h=0);w||0===w||(w=this.length);b||(b=0);if(w!==h&&0!==a.length&&0!==this.length){if(wb||b>=a.length)throw new TypeError("targetStart out of bounds"); +if(0>h||h>=this.length)throw new TypeError("sourceStart out of bounds");if(0>w||w>this.length)throw new TypeError("sourceEnd out of bounds");w>this.length&&(w=this.length);a.length-bw||!e.TYPED_ARRAY_SUPPORT)for(var y=0;yb||b>=this.length)throw new TypeError("start out of bounds"); +if(0>h||h>this.length)throw new TypeError("end out of bounds");if("number"===typeof a)for(;b>1,r=-7;f=t?f-1:0;var k=t?-1:1,u=e[p+f];f+=k;t=u&(1<<-r)-1;u>>=-r;for(r+=c;0>=-r;for(r+=m;0>1,u=23===f?Math.pow(2,-24)-Math.pow(2,-77):0;c=m?0:c-1;var d=m?1:-1,g=0>p||0===p&&0>1/p?1:0;p=Math.abs(p);isNaN(p)||Infinity===p?(p=isNaN(p)?1:0,m=r):(m=Math.floor(Math.log(p)/Math.LN2),1>p*(l=Math.pow(2,-m))&&(m--,l*=2),p=1<=m+k?p+u/l:p+u*Math.pow(2,1-k),2<=p*l&&(m++,l/=2),m+k>=r?(p=0,m=r):1<=m+k?(p=(p*l-1)*Math.pow(2,f),m+=k):(p=p*Math.pow(2,k-1)*Math.pow(2,f),m=0));for(;8<=f;e[t+c]=p&255,c+= +d,p/=256,f-=8);m=m<z?[]:n.slice(v,z-v+1)}c=A.resolve(c).substr(1);l=A.resolve(l).substr(1); +for(var r=q(c.split("/")),k=q(l.split("/")),u=Math.min(r.length,k.length),d=u,g=0;gl&&(l=c.length+l);return c.substr(l,q)}}).call(this,C("g5I+bs"))},{"g5I+bs":9}],9:[function(C,J,A){function e(){}C=J.exports={};C.nextTick=function(){if("undefined"!==typeof window&&window.setImmediate)return function(t){return window.setImmediate(t)};if("undefined"!==typeof window&&window.postMessage&&window.addEventListener){var p=[];window.addEventListener("message",function(t){var m=t.source;m!==window&&null!== +m||"process-tick"!==t.data||(t.stopPropagation(),0p?(-p<<1)+1:p<<1;do p=m&31,m>>>=5,0=f)throw Error("Expected more digits in base 64 VLQ value.");var q=e.decode(p.charCodeAt(t++));if(-1===q)throw Error("Invalid base64 digit: "+p.charAt(t-1));var r=!!(q&32);q&=31;c+=q<>1;m.value=1===(c&1)?-p:p;m.rest=t}},{"./base64":12}],12:[function(C, +J,A){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");A.encode=function(p){if(0<=p&&p=p?p-65:97<=p&&122>=p?p-97+26:48<=p&&57>=p?p-48+52:43==p?62:47==p?63:-1}},{}],13:[function(C,J,A){function e(p,t,m,f,c,l){var q=Math.floor((t-p)/2)+p,r=c(m,f[q],!0);return 0===r?q:0p?-1:p}A.GREATEST_LOWER_BOUND=1;A.LEAST_UPPER_BOUND=2;A.search=function(p,t,m,f){if(0===t.length)return-1;p=e(-1,t.length,p,t,m,f||A.GREATEST_LOWER_BOUND);if(0>p)return-1;for(;0<=p-1&&0===m(t[p],t[p-1],!0);)--p;return p}},{}],14:[function(C,J,A){function e(){this._array=[];this._sorted=!0;this._last={generatedLine:-1,generatedColumn:0}}var p=C("./util");e.prototype.unsortedForEach=function(t,m){this._array.forEach(t,m)};e.prototype.add=function(t){var m=this._last,f=m.generatedLine, +c=t.generatedLine,l=m.generatedColumn,q=t.generatedColumn;c>f||c==f&&q>=l||0>=p.compareByGeneratedPositionsInflated(m,t)?this._last=t:this._sorted=!1;this._array.push(t)};e.prototype.toArray=function(){this._sorted||(this._array.sort(p.compareByGeneratedPositionsInflated),this._sorted=!0);return this._array};A.MappingList=e},{"./util":19}],15:[function(C,J,A){function e(t,m,f){var c=t[m];t[m]=t[f];t[f]=c}function p(t,m,f,c){if(f=m(t[r],q)&&(l+=1,e(t,l,r));e(t,l+1,r);l+=1;p(t,m,f,l-1);p(t,m,l+1,c)}}A.quickSort=function(t,m){p(t,m,0,t.length-1)}},{}],16:[function(C,J,A){function e(k,u){var d=k;"string"===typeof k&&(d=f.parseSourceMapInput(k));return null!=d.sections?new m(d,u):new p(d,u)}function p(k,u){var d=k;"string"===typeof k&&(d=f.parseSourceMapInput(k));var g=f.getArg(d,"version"),n=f.getArg(d,"sources"),v=f.getArg(d,"names",[]),z=f.getArg(d,"sourceRoot",null),G=f.getArg(d,"sourcesContent",null),D=f.getArg(d, +"mappings");d=f.getArg(d,"file",null);if(g!=this._version)throw Error("Unsupported version: "+g);z&&(z=f.normalize(z));n=n.map(String).map(f.normalize).map(function(L){return z&&f.isAbsolute(z)&&f.isAbsolute(L)?f.relative(z,L):L});this._names=l.fromArray(v.map(String),!0);this._sources=l.fromArray(n,!0);this.sourceRoot=z;this.sourcesContent=G;this._mappings=D;this._sourceMapURL=u;this.file=d}function t(){this.generatedColumn=this.generatedLine=0;this.name=this.originalColumn=this.originalLine=this.source= +null}function m(k,u){var d=k;"string"===typeof k&&(d=f.parseSourceMapInput(k));var g=f.getArg(d,"version");d=f.getArg(d,"sections");if(g!=this._version)throw Error("Unsupported version: "+g);this._sources=new l;this._names=new l;var n={line:-1,column:0};this._sections=d.map(function(v){if(v.url)throw Error("Support for url field in sections not implemented.");var z=f.getArg(v,"offset"),G=f.getArg(z,"line"),D=f.getArg(z,"column");if(G=k[d])throw new TypeError("Line must be greater than or equal to 1, got "+ +k[d]);if(0>k[g])throw new TypeError("Column must be greater than or equal to 0, got "+k[g]);return c.search(k,u,n,v)};p.prototype.computeColumnSpans=function(){for(var k=0;k=this._sources.size()&&!this.sourcesContent.some(function(k){return null==k}):!1};p.prototype.sourceContentFor=function(k,u){if(!this.sourcesContent)return null;var d=k;null!=this.sourceRoot&&(d=f.relative(this.sourceRoot,d));if(this._sources.has(d))return this.sourcesContent[this._sources.indexOf(d)]; +var g=this.sources,n;for(n=0;n +g||95!==d.charCodeAt(g-1)||95!==d.charCodeAt(g-2)||111!==d.charCodeAt(g-3)||116!==d.charCodeAt(g-4)||111!==d.charCodeAt(g-5)||114!==d.charCodeAt(g-6)||112!==d.charCodeAt(g-7)||95!==d.charCodeAt(g-8)||95!==d.charCodeAt(g-9))return!1;for(g-=10;0<=g;g--)if(36!==d.charCodeAt(g))return!1;return!0}function r(d,g){return d===g?0:null===d?1:null===g?-1:d>g?1:-1}A.getArg=function(d,g,n){if(g in d)return d[g];if(3===arguments.length)return n;throw Error('"'+g+'" is a required argument.');};var k=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/, +u=/^data:.+,.+$/;A.urlParse=e;A.urlGenerate=p;A.normalize=t;A.join=m;A.isAbsolute=function(d){return"/"===d.charAt(0)||k.test(d)};A.relative=function(d,g){""===d&&(d=".");d=d.replace(/\/$/,"");for(var n=0;0!==g.indexOf(d+"/");){var v=d.lastIndexOf("/");if(0>v)return g;d=d.slice(0,v);if(d.match(/^([^\/]+:\/)?\/*$/))return g;++n}return Array(n+1).join("../")+g.substr(d.length+1)};C=!("__proto__"in Object.create(null));A.toSetString=C?f:c;A.fromSetString=C?f:l;A.compareByOriginalPositions=function(d, +g,n){var v=r(d.source,g.source);if(0!==v)return v;v=d.originalLine-g.originalLine;if(0!==v)return v;v=d.originalColumn-g.originalColumn;if(0!==v||n)return v;v=d.generatedColumn-g.generatedColumn;if(0!==v)return v;v=d.generatedLine-g.generatedLine;return 0!==v?v:r(d.name,g.name)};A.compareByGeneratedPositionsDeflated=function(d,g,n){var v=d.generatedLine-g.generatedLine;if(0!==v)return v;v=d.generatedColumn-g.generatedColumn;if(0!==v||n)return v;v=r(d.source,g.source);if(0!==v)return v;v=d.originalLine- +g.originalLine;if(0!==v)return v;v=d.originalColumn-g.originalColumn;return 0!==v?v:r(d.name,g.name)};A.compareByGeneratedPositionsInflated=function(d,g){var n=d.generatedLine-g.generatedLine;if(0!==n)return n;n=d.generatedColumn-g.generatedColumn;if(0!==n)return n;n=r(d.source,g.source);if(0!==n)return n;n=d.originalLine-g.originalLine;if(0!==n)return n;n=d.originalColumn-g.originalColumn;return 0!==n?n:r(d.name,g.name)};A.parseSourceMapInput=function(d){return JSON.parse(d.replace(/^\)]}'[^\n]*\n/, +""))};A.computeSourceURL=function(d,g,n){g=g||"";d&&("/"!==d[d.length-1]&&"/"!==g[0]&&(d+="/"),g=d+g);if(n){d=e(n);if(!d)throw Error("sourceMapURL could not be parsed");d.path&&(n=d.path.lastIndexOf("/"),0<=n&&(d.path=d.path.substring(0,n+1)));g=m(p(d),g)}return t(g)}},{}],20:[function(C,J,A){A.SourceMapGenerator=C("./lib/source-map-generator").SourceMapGenerator;A.SourceMapConsumer=C("./lib/source-map-consumer").SourceMapConsumer;A.SourceNode=C("./lib/source-node").SourceNode},{"./lib/source-map-consumer":16, +"./lib/source-map-generator":17,"./lib/source-node":18}],21:[function(C,J,A){(function(e){function p(){return"browser"===a?!0:"node"===a?!1:"undefined"!==typeof window&&"function"===typeof XMLHttpRequest&&!(window.require&&window.module&&window.process&&"renderer"===window.process.type)}function t(x){return function(B){for(var F=0;F";B=this.getLineNumber();null!=B&&(x+=":"+B,(B= +this.getColumnNumber())&&(x+=":"+B))}B="";var F=this.getFunctionName(),E=!0,H=this.isConstructor();if(this.isToplevel()||H)H?B+="new "+(F||""):F?B+=F:(B+=x,E=!1);else{H=this.getTypeName();"[object Object]"===H&&(H="null");var M=this.getMethodName();F?(H&&0!=F.indexOf(H)&&(B+=H+"."),B+=F,M&&F.indexOf("."+M)!=F.length-M.length-1&&(B+=" [as "+M+"]")):B+=H+"."+(M||"")}E&&(B+=" ("+x+")");return B}function q(x){var B={};Object.getOwnPropertyNames(Object.getPrototypeOf(x)).forEach(function(F){B[F]= +/^(?:is|get)/.test(F)?function(){return x[F].call(x)}:x[F]});B.toString=l;return B}function r(x,B){void 0===B&&(B={nextPosition:null,curPosition:null});if(x.isNative())return B.curPosition=null,x;var F=x.getFileName()||x.getScriptNameOrSourceURL();if(F){var E=x.getLineNumber(),H=x.getColumnNumber()-1,M=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/,S=M.test;var V="object"===typeof e&&null!==e?e.version:"";M=S.call(M,V)?0:62;1===E&&H>M&&!p()&&!x.isEval()&&(H-=M);var O= +f({source:F,line:E,column:H});B.curPosition=O;x=q(x);var T=x.getFunctionName;x.getFunctionName=function(){return null==B.nextPosition?T():B.nextPosition.name||T()};x.getFileName=function(){return O.source};x.getLineNumber=function(){return O.line};x.getColumnNumber=function(){return O.column+1};x.getScriptNameOrSourceURL=function(){return O.source};return x}var Q=x.isEval()&&x.getEvalOrigin();Q&&(Q=c(Q),x=q(x),x.getEvalOrigin=function(){return Q});return x}function k(x,B){L&&(b={},h={});for(var F= +(x.name||"Error")+": "+(x.message||""),E={nextPosition:null,curPosition:null},H=[],M=B.length-1;0<=M;M--)H.push("\n at "+r(B[M],E)),E.nextPosition=E.curPosition;E.curPosition=E.nextPosition=null;return F+H.reverse().join("")}function u(x){var B=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(x.stack);if(B){x=B[1];var F=+B[2];B=+B[3];var E=b[x];if(!E&&v&&v.existsSync(x))try{E=v.readFileSync(x,"utf8")}catch(H){E=""}if(E&&(E=E.split(/(?:\r\n|\r|\n)/)[F-1]))return x+":"+F+"\n"+E+"\n"+Array(B).join(" ")+ +"^"}return null}function d(){var x=e.emit;e.emit=function(B){if("uncaughtException"===B){var F=arguments[1]&&arguments[1].stack,E=0=12" } }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==", "engines": { - "node": ">= 12" + "node": ">=6.0.0" } }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, "node_modules/acorn": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", @@ -2695,6 +2718,12 @@ "object-assign": "^4.0.1" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash._baseassign": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", @@ -4292,6 +4321,33 @@ "ret": "~0.1.10" } }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -5229,6 +5285,12 @@ "node": ">=0.4" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yargs": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", @@ -5252,10 +5314,30 @@ } }, "dependencies": { - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + "@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true }, "acorn": { "version": "4.0.13", @@ -7416,6 +7498,12 @@ "object-assign": "^4.0.1" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash._baseassign": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", @@ -8801,6 +8889,26 @@ "ret": "~0.1.10" } }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -9608,6 +9716,12 @@ "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yargs": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", diff --git a/package.json b/package.json index 6bcbd26..39120ef 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,20 @@ "/register-hook-require.d.ts", "/register-hook-require.js", "/source-map-support.d.ts", - "/source-map-support.js" + "/source-map-support.js", + "/browser-source-map-support.js" ], "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, "devDependencies": { + "@types/lodash": "^4.14.182", "browserify": "^4.2.3", "coffeescript": "^1.12.7", "http-server": "^0.11.1", + "lodash": "^4.17.21", "mocha": "^3.5.3", + "semver": "^7.3.7", "source-map": "0.6.1", "webpack": "^1.15.0" }, diff --git a/source-map-support.d.ts b/source-map-support.d.ts index 4c112db..d8cb9d8 100755 --- a/source-map-support.d.ts +++ b/source-map-support.d.ts @@ -6,7 +6,15 @@ // Griffin Yourick // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -import { RawSourceMap } from '@cspotcode/source-map-consumer'; +export interface RawSourceMap { + version: 3; + sources: string[]; + names: string[]; + sourceRoot?: string; + sourcesContent?: string[]; + mappings: string; + file: string; +} /** * Output of retrieveSourceMap(). diff --git a/source-map-support.js b/source-map-support.js index 4cbbc0d..b4995ec 100644 --- a/source-map-support.js +++ b/source-map-support.js @@ -1,5 +1,6 @@ -var SourceMapConsumer = require('@cspotcode/source-map-consumer').SourceMapConsumer; +const { TraceMap, originalPositionFor, AnyMap } = require('@jridgewell/trace-mapping'); var path = require('path'); +const { fileURLToPath, pathToFileURL } = require('url'); var util = require('util'); var fs; @@ -92,10 +93,11 @@ var sharedData = initializeSharedData({ emptyCacheBetweenOperations: false, // Maps a file path to a string containing the file contents - fileContentsCache: {}, + fileContentsCache: Object.create(null), // Maps a file path to a source map for that file - sourceMapCache: {}, + /** @type {Record /root-dir/file }); } - if (path in sharedData.fileContentsCache) { - return sharedData.fileContentsCache[path]; + const key = getCacheKey(path); + if(hasFileContentsCacheFromKey(key)) { + return getFileContentsCacheFromKey(key); } var contents = ''; @@ -179,23 +241,74 @@ sharedData.internalRetrieveFileHandlers.push(function(path) { /* ignore any errors */ } - return sharedData.fileContentsCache[path] = contents; + return setFileContentsCache(path, contents); }); // Support URLs relative to a directory, but be careful about a protocol prefix // in case we are in the browser (i.e. directories may start with "http://" or "file:///") function supportRelativeURL(file, url) { - if (!file) return url; - var dir = path.dirname(file); - var match = /^\w+:\/\/[^\/]*/.exec(dir); - var protocol = match ? match[0] : ''; - var startPath = dir.slice(protocol.length); - if (protocol && /^\/\w\:/.test(startPath)) { - // handle file:///C:/ paths - protocol += '/'; - return protocol + path.resolve(dir.slice(protocol.length), url).replace(/\\/g, '/'); + if(!file) return url; + // given that this happens within error formatting codepath, probably best to + // fallback instead of throwing if anything goes wrong + try { + // if should output a URL + if(isAbsoluteUrl(file) || isSchemeRelativeUrl(file)) { + if(isAbsoluteUrl(url) || isSchemeRelativeUrl(url)) { + return new URL(url, file).toString(); + } + if(path.isAbsolute(url)) { + return new URL(pathToFileURL(url), file).toString(); + } + // url is relative path or URL + return new URL(url.replace(/\\/g, '/'), file).toString(); + } + // if should output a path (unless URL is something like https://) + if(path.isAbsolute(file)) { + if(isFileUrl(url)) { + return fileURLToPath(url); + } + if(isSchemeRelativeUrl(url)) { + return fileURLToPath(new URL(url, 'file://')); + } + if(isAbsoluteUrl(url)) { + // url is a non-file URL + // Go with the URL + return url; + } + if(path.isAbsolute(url)) { + // Normalize at all? decodeURI or normalize slashes? + return path.normalize(url); + } + // url is relative path or URL + return path.join(file, '..', decodeURI(url)); + } + // If we get here, file is relative. + // Shouldn't happen since node identifies modules with absolute paths or URLs. + // But we can take a stab at returning something meaningful anyway. + if(isAbsoluteUrl(url) || isSchemeRelativeUrl(url)) { + return url; + } + return path.join(file, '..', url); + } catch(e) { + return url; + } +} + +// Return pathOrUrl in the same style as matchStyleOf: either a file URL or a native path +function matchStyleOfPathOrUrl(matchStyleOf, pathOrUrl) { + try { + if(isAbsoluteUrl(matchStyleOf) || isSchemeRelativeUrl(matchStyleOf)) { + if(isAbsoluteUrl(pathOrUrl) || isSchemeRelativeUrl(pathOrUrl)) return pathOrUrl; + if(path.isAbsolute(pathOrUrl)) return pathToFileURL(pathOrUrl).toString(); + } else if(path.isAbsolute(matchStyleOf)) { + if(isAbsoluteUrl(pathOrUrl) || isSchemeRelativeUrl(pathOrUrl)) { + return fileURLToPath(new URL(pathOrUrl, 'file://')); + } + } + return pathOrUrl; + } catch(e) { + return pathOrUrl; } - return protocol + path.resolve(dir.slice(protocol.length), url); } function retrieveSourceMapURL(source) { @@ -219,7 +332,7 @@ function retrieveSourceMapURL(source) { } // Get the URL of the source map - fileData = retrieveFile(source); + fileData = retrieveFile(tryFileURLToPath(source)); var re = /(?:\/\/[@#][\s]*sourceMappingURL=([^\s'"]+)[\s]*$)|(?:\/\*[@#][\s]*sourceMappingURL=([^\s*'"]+)[\s]*(?:\*\/)[\s]*$)/mg; // Keep executing the search to find the *last* sourceMappingURL to avoid // picking up sourceMappingURLs from comments, strings, etc. @@ -234,6 +347,7 @@ function retrieveSourceMapURL(source) { // there is no source map. The map field may be either a string or the parsed // JSON object (ie, it must be a valid argument to the SourceMapConsumer // constructor). +/** @type {(source: string) => import('./source-map-support').UrlAndMap | null} */ var retrieveSourceMap = handlerExec(sharedData.retrieveMapHandlers, sharedData.internalRetrieveMapHandlers); sharedData.internalRetrieveMapHandlers.push(function(source) { var sourceMappingURL = retrieveSourceMapURL(source); @@ -249,7 +363,7 @@ sharedData.internalRetrieveMapHandlers.push(function(source) { } else { // Support source map URLs relative to the source URL sourceMappingURL = supportRelativeURL(source, sourceMappingURL); - sourceMapData = retrieveFile(sourceMappingURL); + sourceMapData = retrieveFile(tryFileURLToPath(sourceMappingURL)); } if (!sourceMapData) { @@ -263,38 +377,42 @@ sharedData.internalRetrieveMapHandlers.push(function(source) { }); function mapSourcePosition(position) { - var sourceMap = sharedData.sourceMapCache[position.source]; + var sourceMap = getSourceMapCache(position.source); if (!sourceMap) { // Call the (overrideable) retrieveSourceMap function to get the source map. var urlAndMap = retrieveSourceMap(position.source); if (urlAndMap) { - sourceMap = sharedData.sourceMapCache[position.source] = { + sourceMap = setSourceMapCache(position.source, { url: urlAndMap.url, - map: new SourceMapConsumer(urlAndMap.map) - }; + map: new AnyMap(urlAndMap.map, urlAndMap.url) + }); + + // Overwrite trace-mapping's resolutions, because they do not handle + // Windows paths the way we want. + // TODO Remove now that windows path support was added to resolve-uri and thus trace-mapping? + sourceMap.map.resolvedSources = sourceMap.map.sources.map(s => supportRelativeURL(sourceMap.url, s)); // Load all sources stored inline with the source map into the file cache // to pretend like they are already loaded. They may not exist on disk. if (sourceMap.map.sourcesContent) { - sourceMap.map.sources.forEach(function(source, i) { + sourceMap.map.resolvedSources.forEach(function(resolvedSource, i) { var contents = sourceMap.map.sourcesContent[i]; if (contents) { - var url = supportRelativeURL(sourceMap.url, source); - sharedData.fileContentsCache[url] = contents; + setFileContentsCache(resolvedSource, contents); } }); } } else { - sourceMap = sharedData.sourceMapCache[position.source] = { + sourceMap = setSourceMapCache(position.source, { url: null, map: null - }; + }); } } // Resolve the source URL relative to the URL of the source map - if (sourceMap && sourceMap.map && typeof sourceMap.map.originalPositionFor === 'function') { - var originalPosition = sourceMap.map.originalPositionFor(position); + if (sourceMap && sourceMap.map) { + var originalPosition = originalPositionFor(sourceMap.map, position); // Only return the original position if a matching line was found. If no // matching line is found then we return position instead, which will cause @@ -302,8 +420,11 @@ function mapSourcePosition(position) { // better to give a precise location in the compiled file than a vague // location in the original file. if (originalPosition.source !== null) { - originalPosition.source = supportRelativeURL( - sourceMap.url, originalPosition.source); + // originalPosition.source has *already* been resolved against sourceMap.url + // so is *already* as absolute as possible. + // However, we want to ensure we output in same format as input: URL or native path + originalPosition.source = matchStyleOfPathOrUrl( + position.source, originalPosition.source); return originalPosition; } } @@ -337,8 +458,12 @@ function mapEvalOrigin(origin) { } // This is copied almost verbatim from the V8 source code at -// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The -// implementation of wrapCallSite() used to just forward to the actual source +// https://code.google.com/p/v8/source/browse/trunk/src/messages.js +// Update 2022-04-29: +// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/builtins/builtins-callsite.cc#L175-L179 +// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/objects/call-site-info.cc#L795-L804 +// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/objects/call-site-info.cc#L717-L750 +// The implementation of wrapCallSite() used to just forward to the actual source // code of CallSite.prototype.toString but unfortunately a new release of V8 // did something to the prototype chain and broke the shim. The only fix I // could find was copy/paste. @@ -444,6 +569,12 @@ function wrapCallSite(frame, state) { // from getScriptNameOrSourceURL() instead var source = frame.getFileName() || frame.getScriptNameOrSourceURL(); if (source) { + // v8 does not expose its internal isWasm, etc methods, so we do this instead. + if(source.startsWith('wasm://')) { + state.curPosition = null; + return frame; + } + var line = frame.getLineNumber(); var column = frame.getColumnNumber() - 1; @@ -515,8 +646,7 @@ function createPrepareStackTrace(hookState) { if(!hookState.enabled) return hookState.originalValue.apply(this, arguments); if (sharedData.emptyCacheBetweenOperations) { - sharedData.fileContentsCache = {}; - sharedData.sourceMapCache = {}; + clearCaches(); } // node gives its own errors special treatment. Mimic that behavior @@ -555,12 +685,14 @@ function getErrorSource(error) { var column = +match[3]; // Support the inline sourceContents inside the source map - var contents = sharedData.fileContentsCache[source]; + var contents = getFileContentsCache(source); + + const sourceAsPath = tryFileURLToPath(source); // Support files on disk - if (!contents && fs && fs.existsSync(source)) { + if (!contents && fs && fs.existsSync(sourceAsPath)) { try { - contents = fs.readFileSync(source, 'utf8'); + contents = fs.readFileSync(sourceAsPath, 'utf8'); } catch (er) { contents = ''; } @@ -710,8 +842,8 @@ exports.install = function(options) { if (!$compile.__sourceMapSupport) { Module.prototype._compile = function(content, filename) { - sharedData.fileContentsCache[filename] = content; - sharedData.sourceMapCache[filename] = undefined; + setFileContentsCache(filename, content); + setSourceMapCache(filename, undefined); return $compile.call(this, content, filename); }; diff --git a/test-fixtures/wasm/README.md b/test-fixtures/wasm/README.md new file mode 100644 index 0000000..4d6e5cf --- /dev/null +++ b/test-fixtures/wasm/README.md @@ -0,0 +1,12 @@ +To test support for WASM stack traces, we have a tiny WASM module that we call +into. + +It imports a JS function and exports a WASM function +that, when called, will call the JS function. + +When we call the wasm function, it calls back into JS. We can throw an error +and know that one of the stack frames will be wasm. + +The module is described in both text and binary formats. Compilation from text +to binary format was done using an online tool. I didn't bother to set up a +build script, opting instead ot store the binary in version control. diff --git a/test-fixtures/wasm/wasm.js b/test-fixtures/wasm/wasm.js new file mode 100644 index 0000000..602230c --- /dev/null +++ b/test-fixtures/wasm/wasm.js @@ -0,0 +1,14 @@ +const fs = require('fs'); +const path = require('path'); + +exports.call_js_function = async function(fn) { + const mod = await WebAssembly.instantiate( + fs.readFileSync(path.resolve(__dirname, 'wasm.wasm')), + { + jsapi: { + fn + } + } + ); + mod.instance.exports.call_js_function(); +} diff --git a/test-fixtures/wasm/wasm.wasm b/test-fixtures/wasm/wasm.wasm new file mode 100644 index 0000000..f43ee87 Binary files /dev/null and b/test-fixtures/wasm/wasm.wasm differ diff --git a/test-fixtures/wasm/wasm.wat b/test-fixtures/wasm/wasm.wat new file mode 100644 index 0000000..55e12ea --- /dev/null +++ b/test-fixtures/wasm/wasm.wat @@ -0,0 +1,6 @@ +(module + (import "jsapi" "fn" (func $jsapi_fn)) + (func (export "call_js_function") + call $jspapi_fn + ) +) diff --git a/test.js b/test.js index f57cf89..7dabc6c 100644 --- a/test.js +++ b/test.js @@ -1,3 +1,4 @@ +// @ts-check // Note: some tests rely on side-effects from prior tests. // You may not get meaningful results running a subset of tests. @@ -11,170 +12,331 @@ var child_process = require('child_process'); var assert = require('assert'); var fs = require('fs'); var util = require('util'); +var path = require('path'); +const { pathToFileURL } = require('url'); var bufferFrom = Buffer.from; +const semver = require('semver'); +const { once, mapValues, flow } = require('lodash'); + +// Helper to create regular expressions from string templates, to use interpolation +function re(...args) { + return new RegExp(String.raw(...args)); +} + +//#region module format differences +function namedExportDeclaration() { + // same length so that offsets are the same either way + return extension === 'mjs' + ? 'export const test' + : 'exports.test '; +} +/** + * How stack frame will describe invocations of the `test` function, when it is imported and invoked by a different file. + * This varies across CJS / ESM and node versions. + * Example: ` at Module.exports.test (`... + */ +function stackFrameAtTest() { + if(semver.gte(process.versions.node, '18.0.0')) { + return extension === 'mjs' ? 'Module\\.test' : '(?:Module\\.)?exports\\.test'; + } else { + return extension === 'mjs' ? 'Module\\.test' : 'Module\\.exports\\.test'; + } +} +/** + * Describes the first stack frame for `console.trace` which is slightly different in ESM and CJS + */ +function stackFrameAtTrace(fileRe) { + return extension === 'mjs' ? `${fileRe}` : `Object\\. \\(${fileRe}\\)`; +} +/** + * Describe how the source path in a stack frame is expected to start. + * If generated module is ESM, node uses file:// URL, so we expect mapped original path to also be file:// to match + * On windows, when not doing file:// URIs, expect windows-style paths + */ +function stackFramePathStartsWith() { + if(extension === 'mjs') return 'file:/'; + // Escape backslashes since we are returning regexp syntax + return path.parse(process.cwd()).root.replace(/\\/g, '\\\\'); + // this re \((?:.*[/\\])? +} +/** + * Tests were initially written as CJS with require() calls. + * We can support require() calls in MJS tests, too, as long as we create a require() function. + * Keep both prefixes the same length so that offsets are the same + */ +function srcPrefix() { + return extension === 'mjs' + ? `import {createRequire} from 'module';const require = createRequire(import.meta.url);` + : ` `; +} +//#endregion + +// Assign each test a unique ID, to be used in filenames. +// Eliminates need for cache invalidation, because node ESM has no way to +// invalidate cache. +let id = 0; +let extension; +beforeEach(function() { + id++; + extension = 'js'; +}); + +// Consolidate cleanup into a hook so that failed assertions do not leave files +// on disk. +afterEach(function() { + for(const name of [`generated`, `generated2`, `original`, `original2`]) { + for(const suffix of [``, `-separate`, `-inline`]) { + for(const ext of [`js`, `cjs`, `mjs`]) { + for(const ext2 of [``, `.map`, `.map.extra`]) { + const file = `.${name}-${id}${suffix}.${ext}${ext2}`; + fs.existsSync(file) && fs.unlinkSync(file); + } + } + } + } +}); function compareLines(actual, expected) { assert(actual.length >= expected.length, 'got ' + actual.length + ' lines but expected at least ' + expected.length + ' lines\n' + util.inspect({actual, expected})); 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]); + assert(expected[i].test(actual[i]), JSON.stringify(actual[i]) + ' does not match ' + expected[i] + '\n' + JSON.stringify({actual, expected: expected.map(v => typeof v === 'string' ? v : v.toString())}, null, 2)); } 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 sourceMapCreators() { + return { + createEmptySourceMap, + createSourceMapWithGap, + createSingleLineSourceMap, + createSecondLineSourceMap, + createMultiLineSourceMap, + createMultiLineSourceMapWithSourcesContent + }; + function createEmptySourceMap() { + return new SourceMapGenerator({ + file: `.generated-${id}.${extension}`, + sourceRoot: '.' + }); + } -function createSecondLineSourceMap() { - var sourceMap = createEmptySourceMap(); - sourceMap.addMapping({ - generated: { line: 2, column: 0 }, - original: { line: 1, column: 0 }, - source: '.original.js' - }); - return sourceMap; -} + function createSourceMapWithGap() { + var sourceMap = createEmptySourceMap(); + sourceMap.addMapping({ + generated: { line: 100, column: 0 }, + original: { line: 100, column: 0 }, + source: `.original-${id}.js` + }); + return sourceMap; + } -function createMultiLineSourceMap() { - var sourceMap = createEmptySourceMap(); - for (var i = 1; i <= 100; i++) { + function createSingleLineSourceMap() { + var sourceMap = createEmptySourceMap(); sourceMap.addMapping({ - generated: { line: i, column: 0 }, - original: { line: 1000 + i, column: 99 + i }, - source: 'line' + i + '.js' + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: `.original-${id}.js` }); + return sourceMap; } - return sourceMap; -} -function createMultiLineSourceMapWithSourcesContent() { - var sourceMap = createEmptySourceMap(); - var original = new Array(1001).join('\n'); - for (var i = 1; i <= 100; i++) { + function createSecondLineSourceMap() { + var sourceMap = createEmptySourceMap(); sourceMap.addMapping({ - generated: { line: i, column: 0 }, - original: { line: 1000 + i, column: 4 }, - source: 'original.js' + generated: { line: 2, column: 0 }, + original: { line: 1, column: 0 }, + source: `.original-${id}.js` }); - original += ' line ' + i + '\n'; + 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-${id}.js` + }); + original += ' line ' + i + '\n'; + } + sourceMap.setSourceContent(`original-${id}.js`, original); + return sourceMap; } - sourceMap.setSourceContent('original.js', original); - return sourceMap; } -function compareStackTrace(sourceMap, source, expected) { +function rewriteExpectation(expected, generatedFilenameIn, generatedFilenameOut) { + return expected.map(v => { + if(v instanceof RegExp) return new RegExp(v.source.replace(generatedFilenameIn, generatedFilenameOut)); + return v.replace(generatedFilenameIn, generatedFilenameOut); + }); +} +async function compareStackTrace(sourceMap, source, expected) { + const header = srcPrefix(); // Check once with a separate source map - fs.writeFileSync('.generated.js.map', sourceMap.toString()); - fs.writeFileSync('.generated.js', 'exports.test = function() {' + - source.join('\n') + '};//@ sourceMappingURL=.generated.js.map'); + fs.writeFileSync(`.generated-${id}-separate.${extension}.map`, sourceMap.toString()); + fs.writeFileSync(`.generated-${id}-separate.${extension}`, `${header}${namedExportDeclaration()} = function() {` + + source.join('\n') + `};//@ sourceMappingURL=.generated-${id}-separate.${extension}.map`); try { - delete require.cache[require.resolve('./.generated')]; - require('./.generated').test(); + await (await import(`./.generated-${id}-separate.${extension}`)).test(); } catch (e) { - compareLines(e.stack.split(/\r\n|\n/), expected); + compareLines(e.stack.split(/\r\n|\n/), rewriteExpectation(expected, `.generated-${id}`, `.generated-${id}-separate`)); } - 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() {' + + fs.writeFileSync(`.generated-${id}-inline.${extension}`, `${header}${namedExportDeclaration()} = function() {` + source.join('\n') + '};//@ sourceMappingURL=data:application/json;base64,' + bufferFrom(sourceMap.toString()).toString('base64')); try { - delete require.cache[require.resolve('./.generated')]; - require('./.generated').test(); + await (await import (`./.generated-${id}-inline.${extension}`)).test(); } catch (e) { - compareLines(e.stack.split(/\r\n|\n/), expected); + compareLines(e.stack.split(/\r\n|\n/), rewriteExpectation(expected, `.generated-${id}`, `.generated-${id}-inline`)); } - 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.toString()); - fs.writeFileSync('.generated.js', source.join('\n') + - '//@ sourceMappingURL=.generated.js.map'); - child_process.exec('node ./.generated', function(error, stdout, stderr) { + let header = srcPrefix(); + fs.writeFileSync(`.original-${id}.js`, 'this is the original code'); + fs.writeFileSync(`.generated-${id}.${extension}.map`, sourceMap.toString()); + fs.writeFileSync(`.generated-${id}.${extension}`, header + source.join('\n') + + `//@ sourceMappingURL=.generated-${id}.${extension}.map`); + child_process.exec(`node ./.generated-${id}.${extension}`, function(error, stdout, stderr) { try { compareLines( (stdout + stderr) .trim() .split(/\r\n|\n/) - .filter(function (line) { return line !== '' }), // Empty lines are not relevant. + // Empty lines are not relevant. + // Running in a debugger causes additional output. + .filter(function (line) { return line !== '' && line !== 'Debugger attached.' }), expected ); } catch (e) { return done(e); } - fs.unlinkSync('.generated.js'); - fs.unlinkSync('.generated.js.map'); - fs.unlinkSync('.original.js'); done(); }); } -it('normal throw without source-map-support installed', normalThrowWithoutSourceMapSupportInstalled); - -it('normal throw', function() { - installSms(); - normalThrow(); -}); - function installSms() { underTest.install({ emptyCacheBetweenOperations: true // Needed to be able to test for failure }); } +const installSmsOnce = once(installSms); + -function normalThrow() { - compareStackTrace(createMultiLineSourceMap(), [ +function getTestMacros(sourceMapConstructors) { + return {normalThrow, normalThrowWithoutSourceMapSupportInstalled}; +async function normalThrow() { + await compareStackTrace(sourceMapConstructors.createMultiLineSourceMap(), [ 'throw new Error("test");' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]); } -function normalThrowWithoutSourceMapSupportInstalled() { - compareStackTrace(createMultiLineSourceMap(), [ +async function normalThrowWithoutSourceMapSupportInstalled() { + await compareStackTrace(sourceMapConstructors.createMultiLineSourceMap(), [ 'throw new Error("test");' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?\.generated\.js:1:34\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?\.generated-${id}\.${extension}:1:123\)$` ]); } +} + +function describePerModuleType(fn, ...args) { + for(const ext of ['cjs', 'mjs']) { + describe(`${ext} >`, () => { + beforeEach(function() { + extension = ext; + }); + fn(...args); + }); + } +} + +describe('Without source-map-support installed', function() { + describePerModuleType(() => { + const sourceMapConstructors = sourceMapCreators(); + const macros = getTestMacros(sourceMapConstructors); + const {normalThrowWithoutSourceMapSupportInstalled} = macros; + + it('normal throw without source-map-support installed', async function () { + await normalThrowWithoutSourceMapSupportInstalled(); + }); + }); +}); + +function identity(v) {return v} +function addRelativePrefixToSourceMapPaths(sourceMap) { + addPrefixToSourceMapPaths(sourceMap, './'); + return sourceMap; +} +function addAbsolutePrefixToSourceMapPaths(sourceMap) { + addPrefixToSourceMapPaths(sourceMap, '/root/project/'); + return sourceMap; +} +function addFileUrlAbsolutePrefixToSourceMapPaths(sourceMap) { + addPrefixToSourceMapPaths(sourceMap, 'file:///root/project/'); + return sourceMap; +} +function addPrefixToSourceMapPaths(sourceMap, prefix) { + function addPrefix(path) {return `${prefix}${path}`} + sourceMap.file = addPrefix(sourceMap.file); + if(sourceMap.sources) sourceMap.sources = sourceMap.sources.map(addPrefix); + return sourceMap; +} + +describe('sourcemap style: relative paths sans ./ prefix, e.g. "original-1.js" >', () => { + describePerModuleType(tests, identity); +}); +describe('sourcemap style: relative paths with ./ prefix, e.g. "./original-1.js" >', () => { + describePerModuleType(tests, addRelativePrefixToSourceMapPaths); +}); +describe('sourcemap style: absolute paths and sourceRoot removed, e.g. "/abs/path/original-1.js" >', () => { + describePerModuleType(tests, addAbsolutePrefixToSourceMapPaths); +}); +describe('sourcemap style: file urls with absolute paths and sourceRoot removed, e.g. "file:///abs/path/original-1.js" >', () => { + describePerModuleType(tests, addFileUrlAbsolutePrefixToSourceMapPaths); +}); + +function tests(sourceMapPostprocessor) { + // let createEmptySourceMap, createMultiLineSourceMap, createMultiLineSourceMapWithSourcesContent, createSecondLineSourceMap, createSingleLineSourceMap, createSourceMapWithGap}) + const sourceMapConstructors = mapValues(sourceMapCreators(), v => flow(v, sourceMapPostprocessor)); + const {createEmptySourceMap, createMultiLineSourceMap, createMultiLineSourceMapWithSourcesContent, createSecondLineSourceMap, createSingleLineSourceMap, createSourceMapWithGap} = sourceMapConstructors; + const {normalThrow} = getTestMacros(sourceMapConstructors); + + // Run as a hook to ensure it runs even when we execute a subset of tests + before(installSmsOnce); + +it('normal throw', async function() { + await normalThrow(); +}); /* The following test duplicates some of the code in * `normal throw` but triggers file read failure. */ -it('fs.readFileSync failure', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('fs.readFileSync failure', async function() { + await compareStackTrace(createMultiLineSourceMap(), [ 'var fs = require("fs");', 'var rfs = fs.readFileSync;', 'fs.readFileSync = function() {', @@ -187,26 +349,26 @@ it('fs.readFileSync failure', function() { '}' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?line7\.js:1007:107\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line7\.js:1007:107\)$` ]); }); -it('throw inside function', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('throw inside function', async function() { + await 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\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line2\.js:1002:102\)$`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line4\.js:1004:104\)$` ]); }); -it('throw inside function inside function', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('throw inside function inside function', async function() { + await compareStackTrace(createMultiLineSourceMap(), [ 'function foo() {', ' function bar() {', ' throw new Error("test");', @@ -216,95 +378,177 @@ it('throw inside function inside function', function() { 'foo();' ], [ 'Error: test', - /^ at bar \((?:.*[/\\])?line3\.js:1003:103\)$/, - /^ at foo \((?:.*[/\\])?line5\.js:1005:105\)$/, - /^ at Object\.exports\.test \((?:.*[/\\])?line7\.js:1007:107\)$/ + re`^ at bar \(${stackFramePathStartsWith()}(?:.*[/\\])?line3\.js:1003:103\)$`, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line5\.js:1005:105\)$`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line7\.js:1007:107\)$` ]); }); -it('eval', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('eval', async function() { + await compareStackTrace(createMultiLineSourceMap(), [ 'eval("throw new Error(\'test\')");' ], [ 'Error: test', - // Before Node 4, `Object.eval`, after just `eval`. - /^ at (?:Object\.)?eval \(eval at (|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/, + re`^ at eval \(eval at (|exports\.test|test) \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)`, - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]); }); -it('eval inside eval', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('eval inside eval', async function() { + await compareStackTrace(createMultiLineSourceMap(), [ 'eval("eval(\'throw new Error(\\"test\\")\')");' ], [ 'Error: test', - /^ at (?:Object\.)?eval \(eval at (|exports.test) \(eval at (|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/, - /^ at (?:Object\.)?eval \(eval at (|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/, - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + re`^ at eval \(eval at (|exports\.test|test) \(eval at (|exports\.test|test) \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)`, + re`^ at eval \(eval at (|exports\.test|test) \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]); }); -it('eval inside function', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('eval inside function', async function() { + await 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\)$/ + re`^ at eval \(eval at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line2\.js:1002:102\)`, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line2\.js:1002:102\)`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line4\.js:1004:104\)$` ]); }); -it('eval with sourceURL', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('eval with sourceURL', async function() { + await 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\)$/ + /^ at eval \(sourceURL\.js:1:7\)$/, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]); }); -it('eval with sourceURL inside eval', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('eval with sourceURL inside eval', async function() { + await 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 (|exports.test) \((?:.*[/\\])?line1\.js:1001:101\)/, - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + /^ at eval \(sourceURL\.js:1:7\)$/, + re`^ at eval \(eval at (|exports.test|test) \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]); }); -it('native function', function() { - compareStackTrace(createSingleLineSourceMap(), [ +it('native function', async function() { + await compareStackTrace(createSingleLineSourceMap(), [ '[1].map(function(x) { throw new Error(x); });' ], [ 'Error: 1', - /[/\\].original\.js/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.original-${id}.js`, /at Array\.map \((native|)\)/ ]); }); -it('function constructor', function() { - compareStackTrace(createMultiLineSourceMap(), [ +it('function constructor', async function() { + await compareStackTrace(createMultiLineSourceMap(), [ 'throw new Function(")");' ], [ /SyntaxError: Unexpected token '?\)'?/, ]); }); -it('throw with empty source map', function() { - compareStackTrace(createEmptySourceMap(), [ +it('Verify node does not support Promise.allSettled stack frames. When this test starts breaking, we need to start testing for Promise.allSettled.', async () => { + // results1/driver1 is not strictly necessary to test allSettled; it is here to remind myself how to correctly get Promise.* methods to appear in a stack trace. + let result1; + await driver1().catch(e => result1 = e); + assert.match(result1.stack, /\bPromise\.all\b/); + + // Copied from V8 tests: https://github.com/v8/v8/commit/89ed081c176e286f9d65f3821d43f568cd56a035#diff-1a0a032688d7546dcfe5730eaab2854fb1b8dab656d8bb940dffc71b7b975aae + async function fine() { } + async function thrower() { + await fine(); + throw new Error(); + } + async function driver1() { + return await Promise.all([fine(), fine(), thrower(), thrower()]); + } + async function driver2() { + return await Promise.allSettled([fine(), fine(), thrower(), thrower()]); + } + + const results2 = await driver2(); + assert.equal(results2[2].status, 'rejected'); + assert.doesNotMatch(results2[2].reason.stack, /\bPromise\.allSettled\b/); +}); + +it('async stack frames: async, Promise.all'/*Promise.allSettled*/, async function() { + await compareStackTrace(createMultiLineSourceMap(), [ + // Add once node upgrades to v8 10.2, where this was added: https://github.com/v8/v8/commit/89ed081c176e286f9d65f3821d43f568cd56a035 + // 'async function foo() { return await bar(); }', + // 'async function bar() { return await Promise.allSettled([baz()]) }', + + 'async function foo() { return await bar(); }', + 'async function bar() { await Promise.all([baz()]) }', + 'async function baz() { await null; throw new Error("test"); }', + 'return foo();' + ], [ + 'Error: test', + re`^ at baz \(${stackFramePathStartsWith()}(?:.*[/\\])?line3.js:1003:103\)$`, + re`^ at async Promise\.all \(index 0\)$`, + re`^ at async bar \(${stackFramePathStartsWith()}(?:.*[/\\])?line2.js:1002:102\)$`, + re`^ at async foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line1.js:1001:101\)$` + ]); +}); + +it('async stack frames: Promise.any', async function() { + // node 14 and older does not have Promise.any + if(semver.lt(process.versions.node, '16.0.0')) return this.skip(); + + await compareStackTrace(createMultiLineSourceMap(), [ + // Add once node upgrades to v8 10.2, where this was added: https://github.com/v8/v8/commit/89ed081c176e286f9d65f3821d43f568cd56a035 + // 'async function foo() { return await bar(); }', + // 'async function bar() { return await Promise.allSettled([baz()]) }', + + 'async function foo() { return await bar(); }', + 'async function bar() { await Promise.any([baz()]); }', + 'async function baz() { await null; throw new Error("test"); }', + 'return foo().catch(e => { throw e.errors[0] })' + ], [ + 'Error: test', + re`^ at baz \(${stackFramePathStartsWith()}(?:.*[/\\])?line3.js:1003:103\)$`, + re`^ at async Promise\.any \(index 0\)$`, + re`^ at async bar \(${stackFramePathStartsWith()}(?:.*[/\\])?line2.js:1002:102\)$`, + re`^ at async foo \(${stackFramePathStartsWith()}(?:.*[/\\])?line1.js:1001:101\)$` + ]); +}); + +it('wasm stack frames', async function() { + const wasmFrame = semver.gte(process.versions.node, '16.0.0') + ? String.raw`wasm:\/\/wasm\/c2de0ab2:wasm-function\[1\]:0x3b` + : semver.gte(process.versions.node, '14.0.0') + ? String.raw`call_js_function \(:wasm-function\[1\]:0x3b\)` + // Node 12 + : String.raw`wasm-function\[1\]:0x3b`; + + await compareStackTrace(createMultiLineSourceMap(), [ + 'return require("./test-fixtures/wasm/wasm.js").call_js_function(() => { throw new Error("test"); });' + ], [ + 'Error: test', + re`^ at ${stackFramePathStartsWith()}(?:.*[/\\])?line1.js:1001:101$`, + re`^ at ${wasmFrame}$`, + re`^ at Object\.exports\.call_js_function \(.*[/\\]wasm\.js:13:24\)$`, + ]); +}); + +it('throw with empty source map', async function() { + await compareStackTrace(createEmptySourceMap(), [ 'throw new Error("test");' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?\.generated.js:1:34\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?\.generated-${id}.${extension}:1:123\)$` ]); }); @@ -315,64 +559,64 @@ it('throw in Timeout with empty source map', function(done) { ' throw new Error("this is the error")', '})' ], [ - /[/\\].generated.js:3$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:3$`, ' throw new Error("this is the error")', /^ \^$/, 'Error: this is the error', - /^ at ((null)|(Timeout))\._onTimeout \((?:.*[/\\])?.generated\.js:3:11\)$/ + re`^ at ((null)|(Timeout))\._onTimeout \(${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}\.${extension}:3:11\)$` ]); }); -it('throw with source map with gap', function() { - compareStackTrace(createSourceMapWithGap(), [ +it('throw with source map with gap', async function() { + await compareStackTrace(createSourceMapWithGap(), [ 'throw new Error("test");' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?\.generated\.js:1:34\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?\.generated-${id}\.${extension}:1:123\)$` ]); }); -it('sourcesContent with data URL', function() { - compareStackTrace(createMultiLineSourceMapWithSourcesContent(), [ +it('sourcesContent with data URL', async function() { + await compareStackTrace(createMultiLineSourceMapWithSourcesContent(), [ 'throw new Error("test");' ], [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?original\.js:1001:5\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1001:5\)$` ]); }); -it('finds the last sourceMappingURL', function() { - compareStackTrace(createMultiLineSourceMapWithSourcesContent(), [ +it('finds the last sourceMappingURL', async function() { + await 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\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1002:5\)$` ]); }); -it('maps original name from source', function() { +it('maps original name from source', async function() { var sourceMap = createEmptySourceMap(); sourceMap.addMapping({ generated: { line: 2, column: 8 }, original: { line: 1000, column: 10 }, - source: '.original.js', + source: `.original-${id}.js`, }); sourceMap.addMapping({ generated: { line: 4, column: 0 }, original: { line: 1002, column: 1 }, - source: ".original.js", + source: `.original-${id}.js`, name: "myOriginalName" }); - compareStackTrace(sourceMap, [ + await compareStackTrace(sourceMap, [ 'function foo() {', ' throw new Error("test");', '}', 'foo();' ], [ 'Error: test', - /^ at myOriginalName \((?:.*[/\\])?\.original.js:1000:11\)$/, - /^ at Object\.exports\.test \((?:.*[/\\])?\.original.js:1002:2\)$/ + re`^ at myOriginalName \(${stackFramePathStartsWith()}(?:.*[/\\])?\.original-${id}.js:1000:11\)$`, + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?\.original-${id}.js:1002:2\)$` ]); }); @@ -384,11 +628,11 @@ it('default options', function(done) { 'process.nextTick(foo);', 'process.nextTick(function() { process.exit(1); });' ], [ - /[/\\].original\.js:1$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.original-${id}\.js:1$`, 'this is the original code', '^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?\.original\.js:1:1\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?\.original-${id}\.js:1:1\)$` ]); }); @@ -399,11 +643,11 @@ it('handleUncaughtExceptions is true', function(done) { 'require("./source-map-support").install({ handleUncaughtExceptions: true });', 'process.nextTick(foo);' ], [ - /[/\\].original\.js:1$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.original-${id}\.js:1$`, 'this is the original code', '^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?\.original\.js:1:1\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?\.original-${id}\.js:1:1\)$` ]); }); @@ -414,15 +658,13 @@ it('handleUncaughtExceptions is false', function(done) { 'require("./source-map-support").install({ handleUncaughtExceptions: false });', 'process.nextTick(foo);' ], [ - /[/\\].generated.js:2$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}: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\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?.original-${id}\.js:1:1\)$` ]); }); @@ -433,11 +675,11 @@ it('default options with empty source map', function(done) { 'require("./source-map-support").install();', 'process.nextTick(foo);' ], [ - /[/\\].generated.js:2$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:2$`, 'function foo() { throw new Error("this is the error"); }', - /^ (?: )?\^$/, + ' ^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?.generated.js:2:24\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:2:24\)$` ]); }); @@ -448,11 +690,11 @@ it('default options with source map with gap', function(done) { 'require("./source-map-support").install();', 'process.nextTick(foo);' ], [ - /[/\\].generated.js:2$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:2$`, 'function foo() { throw new Error("this is the error"); }', - /^ (?: )?\^$/, + ' ^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?.generated.js:2:24\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:2:24\)$` ]); }); @@ -465,7 +707,7 @@ it('specifically requested error source', function(done) { 'process.on("uncaughtException", function (e) { console.log("SRC:" + sms.getErrorSource(e)); });', 'process.nextTick(foo);' ], [ - /^SRC:.*[/\\]\.original\.js:1$/, + re`^SRC:.*[/\\]\.original-${id}\.js:1$`, 'this is the original code', '^' ]); @@ -479,11 +721,11 @@ it('sourcesContent', function(done) { 'process.nextTick(foo);', 'process.nextTick(function() { process.exit(1); });' ], [ - /[/\\]original\.js:1002$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1002$`, ' line 2', ' ^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?original\.js:1002:5\)$/ + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1002:5\)$` ]); }); @@ -497,7 +739,7 @@ it('missing source maps should also be cached', function(done) { 'require("./source-map-support").install({', ' overrideRetrieveSourceMap: true,', ' retrieveSourceMap: function(name) {', - ' if (/\\.generated.js$/.test(name)) count++;', + ' if (/\\.generated-\\d+\\.(js|cjs|mjs)$/.test(name)) count++;', ' return null;', ' }', '});', @@ -506,14 +748,18 @@ it('missing source maps should also be cached', function(done) { 'process.nextTick(function() { console.log(count); });', ], [ 'Error: this is the error', - /^ at foo \((?:.*[/\\])?.generated.js:4:15\)$/, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:4:15\)$`, 'Error: this is the error', - /^ at foo \((?:.*[/\\])?.generated.js:4:15\)$/, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?.generated-${id}.${extension}:4:15\)$`, '1', // The retrieval should only be attempted once ]); }); it('should consult all retrieve source map providers', function(done) { + // TODO are we supposed to be resolving this URL to absolute? Or should we test that non-absolute is supported? + // Test in vanilla source-map-support + let originalPath = path.resolve(`.original-${id}.js`); + if(extension === 'mjs') originalPath = pathToFileURL(originalPath).toString(); compareStdout(done, createSingleLineSourceMap(), [ '', 'var count = 0;', @@ -522,15 +768,15 @@ it('should consult all retrieve source map providers', function(done) { '}', 'require("./source-map-support").install({', ' retrieveSourceMap: function(name) {', - ' if (/\\.generated.js$/.test(name)) count++;', + ` if (/\\.generated-${id}\\.${extension}$/.test(name)) count++;`, ' return undefined;', ' }', '});', 'require("./source-map-support").install({', ' retrieveSourceMap: function(name) {', - ' if (/\\.generated.js$/.test(name)) {', + ` if (/\\.generated-${id}\\.${extension}$/.test(name)) {`, ' count++;', - ' return ' + JSON.stringify({url: '.original.js', map: createMultiLineSourceMapWithSourcesContent().toJSON()}) + ';', + ' return ' + JSON.stringify({url: originalPath, map: createMultiLineSourceMapWithSourcesContent().toJSON()}) + ';', ' }', ' }', '});', @@ -539,9 +785,9 @@ it('should consult all retrieve source map providers', function(done) { 'process.nextTick(function() { console.log(count); });', ], [ 'Error: this is the error', - /^ at foo \((?:.*[/\\])?original\.js:1004:5\)$/, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1004:5\)$`, 'Error: this is the error', - /^ at foo \((?:.*[/\\])?original\.js:1004:5\)$/, + re`^ at foo \(${stackFramePathStartsWith()}(?:.*[/\\])?original-${id}\.js:1004:5\)$`, '1', // The retrieval should only be attempted once ]); }); @@ -576,9 +822,9 @@ it('should allow for runtime inline source maps', function(done) { 'require("./.generated.jss");', ], [ 'Error: this is the error', - /^ at foo \(.*[/\\]original\.js:1004:5\)$/, + re`^ at foo \(.*[/\\]original-${id}\.js:1004:5\)$`, 'Error: this is the error', - /^ at foo \(.*[/\\]original\.js:1004:5\)$/, + re`^ at foo \(.*[/\\]original-${id}\.js:1004:5\)$`, '0', // The retrieval should only be attempted once ]); }); @@ -587,49 +833,45 @@ it('should allow for runtime inline source maps', function(done) { * `compareStackTrace` but appends a charset to the * source mapping url. */ -it('finds source maps with charset specified', function() { +it('finds source maps with charset specified', async function() { var sourceMap = createMultiLineSourceMap() var source = [ 'throw new Error("test");' ]; var expected = [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]; - fs.writeFileSync('.generated.js', 'exports.test = function() {' + + fs.writeFileSync(`.generated-${id}.${extension}`, `${namedExportDeclaration()} = function() {` + source.join('\n') + '};//@ sourceMappingURL=data:application/json;charset=utf8;base64,' + bufferFrom(sourceMap.toString()).toString('base64')); try { - delete require.cache[require.resolve('./.generated')]; - require('./.generated').test(); + (await import(`./.generated-${id}.${extension}`)).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() { +it('allows code/comments after sourceMappingURL', async function() { var sourceMap = createMultiLineSourceMap() var source = [ 'throw new Error("test");' ]; var expected = [ 'Error: test', - /^ at Object\.exports\.test \((?:.*[/\\])?line1\.js:1001:101\)$/ + re`^ at ${stackFrameAtTest()} \(${stackFramePathStartsWith()}(?:.*[/\\])?line1\.js:1001:101\)$` ]; - fs.writeFileSync('.generated.js', 'exports.test = function() {' + + fs.writeFileSync(`.generated-${id}.${extension}`, `${namedExportDeclaration()} = function() {` + source.join('\n') + '};//# sourceMappingURL=data:application/json;base64,' + bufferFrom(sourceMap.toString()).toString('base64') + '\n// Some comment below the sourceMappingURL\nvar foo = 0;'); try { - delete require.cache[require.resolve('./.generated')]; - require('./.generated').test(); + (await import(`./.generated-${id}.${extension}`)).test(); } catch (e) { compareLines(e.stack.split(/\r\n|\n/), expected); } - fs.unlinkSync('.generated.js'); }); it('handleUncaughtExceptions is true with existing listener', function(done) { @@ -638,17 +880,14 @@ it('handleUncaughtExceptions is true with existing listener', function(done) { 'function foo() { throw new Error("this is the error"); }', 'require("./source-map-support").install();', 'process.nextTick(foo);', - '//@ sourceMappingURL=.generated.js.map' + `//@ sourceMappingURL=.generated-${id}.${extension}.map` ]; - fs.writeFileSync('.original.js', 'this is the original code'); - fs.writeFileSync('.generated.js.map', createSingleLineSourceMap().toString()); - fs.writeFileSync('.generated.js', source.join('\n')); + fs.writeFileSync(`.original-${id}.js`, 'this is the original code'); + fs.writeFileSync(`.generated-${id}.${extension}.map`, createSingleLineSourceMap().toString()); + fs.writeFileSync(`.generated-${id}.${extension}`, 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'); + child_process.exec(`node ./.generated-${id}.${extension}`, function(error, stdout, stderr) { assert.equal((stdout + stderr).trim(), ''); done(); }); @@ -660,60 +899,60 @@ it('normal console.trace', function(done) { 'console.trace("test");' ], [ 'Trace: test', - /^ at Object\. \((?:.*[/\\])?line2\.js:1002:102\)$/ + re`^ at ${stackFrameAtTrace(String.raw`(?:.*[/\\])?line2\.js:1002:102`)}$` ]); }); it('supports multiple instances', function(done) { - function finish(err) { - fs.unlinkSync('.original2.js'); - fs.unlinkSync('.generated2.js'); - fs.unlinkSync('.generated2.js.map.extra') - done(err); - } var sourceMap = createEmptySourceMap(); sourceMap.addMapping({ generated: { line: 1, column: 0 }, original: { line: 1, column: 0 }, - source: '.original2.js' + source: `.original2-${id}.js` }); - fs.writeFileSync('.generated2.js.map.extra', sourceMap.toString()); - fs.writeFileSync('.generated2.js', [ - 'module.exports = function foo() { throw new Error("this is the error"); }', - '//@ sourceMappingURL=.generated2.js.map' + fs.writeFileSync(`.generated2-${id}.${extension}.map.extra`, sourceMap.toString()); + fs.writeFileSync(`.generated2-${id}.${extension}`, [ + `${namedExportDeclaration()} = function test() { throw new Error("this is the error"); }`, + `//@ sourceMappingURL=.generated2-${id}.${extension}.map` ].join('\n')); - fs.writeFileSync('.original2.js', 'this is some other original code'); - compareStdout(finish, createEmptySourceMap(), [ - 'require("./source-map-support").install({', - ' retrieveFile: function(path) {', - ' var fs = require("fs");', - ' if (fs.existsSync(path + ".extra")) {', - ' return fs.readFileSync(path + ".extra", "utf8");', + fs.writeFileSync(`.original2-${id}.js`, 'this is some other original code'); + compareStdout(done, createEmptySourceMap(), [ + '(async function() {', + ' require("./source-map-support").install({', + ' retrieveFile: function(path) {', + ' var fs = require("fs");', + ' var url = require("url");', + ' try { path = url.fileURLToPath(path) } catch {}', + ' if (fs.existsSync(path + ".extra")) {', + ' return fs.readFileSync(path + ".extra", "utf8");', + ' }', ' }', - ' }', - '});', - 'var foo = require("./.generated2.js");', - 'delete require.cache[require.resolve("./source-map-support")];', - 'require("./source-map-support").install();', - 'process.nextTick(foo);', - 'process.nextTick(function() { process.exit(1); });' + ' });', + ` var {test} = await import("./.generated2-${id}.${extension}");`, + ' delete require.cache[require.resolve("./source-map-support")];', + ' require("./source-map-support").install();', + ' process.nextTick(test);', + ' process.nextTick(function() { process.exit(1); });', + '})();' ], [ - /[/\\].original2\.js:1$/, + re`${stackFramePathStartsWith()}(?:.*[/\\])?.original2-${id}\.js:1$`, 'this is some other original code', '^', 'Error: this is the error', - /^ at foo \((?:.*[/\\])?.original2\.js:1:1\)$/ + re`^ at test \(${stackFramePathStartsWith()}(?:.*[/\\])?.original2-${id}\.js:1:1\)$` ]); }); +} describe('redirects require() of "source-map-support" to this module', function() { - it('redirects', function() { + before(installSmsOnce); + it('redirects', async function() { assert.strictEqual(require.resolve('source-map-support'), require.resolve('.')); assert.strictEqual(require.resolve('source-map-support/register'), require.resolve('./register')); assert.strictEqual(require('source-map-support'), require('.')); }); - it('emits notifications', function() { + it('emits notifications', async function() { let onConflictingLibraryRedirectCalls = []; let onConflictingLibraryRedirectCalls2 = []; underTest.install({ @@ -741,6 +980,10 @@ describe('redirects require() of "source-map-support" to this module', function( }); describe('uninstall', function() { + const sourceMapConstructors = sourceMapCreators(); + const {normalThrow, normalThrowWithoutSourceMapSupportInstalled} = getTestMacros(sourceMapConstructors); + + before(installSmsOnce); this.beforeEach(function() { underTest.uninstall(); process.emit = priorProcessEmit; @@ -748,19 +991,19 @@ describe('uninstall', function() { Module._resolveFilename = priorResolveFilename; }); - it('uninstall removes hooks and source-mapping behavior', function() { + it('uninstall removes hooks and source-mapping behavior', async function() { assert.strictEqual(Error.prepareStackTrace, priorErrorPrepareStackTrace); assert.strictEqual(process.emit, priorProcessEmit); assert.strictEqual(Module._resolveFilename, priorResolveFilename); - normalThrowWithoutSourceMapSupportInstalled(); + await normalThrowWithoutSourceMapSupportInstalled(); }); - it('install re-adds hooks', function() { + it('install re-adds hooks', async function() { installSms(); - normalThrow(); + await normalThrow(); }); - it('uninstall removes prepareStackTrace even in presence of third-party hooks if none were installed before us', function() { + it('uninstall removes prepareStackTrace even in presence of third-party hooks if none were installed before us', async function() { installSms(); const wrappedPrepareStackTrace = Error.prepareStackTrace; let pstInvocations = 0; @@ -774,7 +1017,7 @@ describe('uninstall', function() { assert(pstInvocations === 0); }); - it('uninstall preserves third-party prepareStackTrace hooks if one was installed before us', function() { + it('uninstall preserves third-party prepareStackTrace hooks if one was installed before us', async function() { let beforeInvocations = 0; function thirdPartyPrepareStackTraceHookInstalledBefore() { beforeInvocations++; @@ -796,7 +1039,7 @@ describe('uninstall', function() { assert.strictEqual(afterInvocations, 1); }); - it('uninstall preserves third-party process.emit hooks installed after us', function() { + it('uninstall preserves third-party process.emit hooks installed after us', async function() { installSms(); const wrappedProcessEmit = process.emit; let peInvocations = 0; @@ -807,12 +1050,12 @@ describe('uninstall', function() { process.emit = thirdPartyProcessEmit; underTest.uninstall(); assert.strictEqual(process.emit, thirdPartyProcessEmit); - normalThrowWithoutSourceMapSupportInstalled(); + await normalThrowWithoutSourceMapSupportInstalled(); process.emit('foo'); assert(peInvocations >= 1); }); - it('uninstall preserves third-party module._resolveFilename hooks installed after us', function() { + it('uninstall preserves third-party module._resolveFilename hooks installed after us', async function() { installSms(); const wrappedResolveFilename = Module._resolveFilename; let peInvocations = 0; @@ -823,8 +1066,11 @@ describe('uninstall', function() { Module._resolveFilename = thirdPartyModuleResolveFilename; underTest.uninstall(); assert.strictEqual(Module._resolveFilename, thirdPartyModuleResolveFilename); - normalThrowWithoutSourceMapSupportInstalled(); + await normalThrowWithoutSourceMapSupportInstalled(); Module._resolveFilename('repl'); assert(peInvocations >= 1); }); }); +// Without this, the code under test sees stuff in the test cases above and tries to load source-maps +// This causes confusing red herrings while debugging. +//#sourceMappingURL=test.js.map-intentionally-does-not-exist \ No newline at end of file