source map 还原js报错
最近在做前端全链路监控,其中一个功能就是根据sdk上报的错误信息利用source map进行还原
上报信息类似这样
{
file: '../../node_modules/downloadjs/download.js',
message: 'Uncaught ReferenceError: data is not defined',
line: 1,
column: 200,
}
包括报错信息,所在行列,然后就希望可以通过源码的source map 还原成这样子
思路是使用mozilla的source-map https://github.com/mozilla/source-map
1.修改打包配置,这里是使用vite
build: {
sourcemap: true,
//...其他配置
}
2.新建index.html,引入sourcemap包
<script src="https://unpkg.com/source-map@0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm":
"https://unpkg.com/source-map@0.7.3/lib/mappings.wasm",
});
</script>
3.获取代码的source map,这里为了方便演示,直接用一个对象代替,真正到生产的时候,可以直接通过服务去自动读取
const file = {
version: 3,
file: "downloadjs-legacy-b08799ac.js",
sources: ["../../node_modules/downloadjs/download.js"],
sourcesContent: [
'//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage\n// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime\n// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs\n// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.\n// v4 adds AMD/UMD, commonJS, and plain browser support\n// v4.1 adds url download capability via solo URL argument (same domain/CORS only)\n// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors\n// https://github.com/rndme/download\n\n(function (root, factory) {\n\tif (typeof define === \'function\' && define.amd) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([], factory);\n\t} else if (typeof exports === \'object\') {\n\t\t// Node. Does not work with strict CommonJS, but\n\t\t// only CommonJS-like environments that support module.exports,\n\t\t// like Node.\n\t\tmodule.exports = factory();\n\t} else {\n\t\t// Browser globals (root is window)\n\t\troot.download = factory();\n }\n}(this, function () {\n\n\treturn function download(data, strFileName, strMimeType) {\n\n\t\tvar self = window, // this script is only for browsers anyway...\n\t\t\tdefaultMime = "application/octet-stream", // this default mime also triggers iframe downloads\n\t\t\tmimeType = strMimeType || defaultMime,\n\t\t\tpayload = data,\n\t\t\turl = !strFileName && !strMimeType && payload,\n\t\t\tanchor = document.createElement("a"),\n\t\t\ttoString = function(a){return String(a);},\n\t\t\tmyBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),\n\t\t\tfileName = strFileName || "download",\n\t\t\tblob,\n\t\t\treader;\n\t\t\tmyBlob= myBlob.call ? myBlob.bind(self) : Blob ;\n\t \n\t\tif(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback\n\t\t\tpayload=[payload, mimeType];\n\t\t\tmimeType=payload[0];\n\t\t\tpayload=payload[1];\n\t\t}\n\n\n\t\tif(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument\n\t\t\tfileName = url.split("/").pop().split("?")[0];\n\t\t\tanchor.href = url; // assign href prop to temp anchor\n\t\t \tif(anchor.href.indexOf(url) !== -1){ // if the browser determines that it\'s a potentially valid url path:\n \t\tvar ajax=new XMLHttpRequest();\n \t\tajax.open( "GET", url, true);\n \t\tajax.responseType = \'blob\';\n \t\tajax.onload= function(e){ \n\t\t\t\t download(e.target.response, fileName, defaultMime);\n\t\t\t\t};\n \t\tsetTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:\n\t\t\t return ajax;\n\t\t\t} // end if valid url?\n\t\t} // end if url?\n\n\n\t\t//go ahead and download dataURLs right away\n\t\tif(/^data:([\\w+-]+\\/[\\w+.-]+)?[,;]/.test(payload)){\n\t\t\n\t\t\tif(payload.length > (1024*1024*1.999) && myBlob !== toString ){\n\t\t\t\tpayload=dataUrlToBlob(payload);\n\t\t\t\tmimeType=payload.type || defaultMime;\n\t\t\t}else{\t\t\t\n\t\t\t\treturn navigator.msSaveBlob ? // IE10 can\'t do a[download], only Blobs:\n\t\t\t\t\tnavigator.msSaveBlob(dataUrlToBlob(payload), fileName) :\n\t\t\t\t\tsaver(payload) ; // everyone else can save dataURLs un-processed\n\t\t\t}\n\t\t\t\n\t\t}else{//not data url, is it a string with special needs?\n\t\t\tif(/([\\x80-\\xff])/.test(payload)){\t\t\t \n\t\t\t\tvar i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;\n\t\t\t\tfor(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);\n\t\t\t \tpayload=new myBlob([tempUiArr], {type: mimeType});\n\t\t\t}\t\t \n\t\t}\n\t\tblob = payload instanceof myBlob ?\n\t\t\tpayload :\n\t\t\tnew myBlob([payload], {type: mimeType}) ;\n\n\n\t\tfunction dataUrlToBlob(strUrl) {\n\t\t\tvar parts= strUrl.split(/[:;,]/),\n\t\t\ttype= parts[1],\n\t\t\tdecoder= parts[2] == "base64" ? atob : decodeURIComponent,\n\t\t\tbinData= decoder( parts.pop() ),\n\t\t\tmx= binData.length,\n\t\t\ti= 0,\n\t\t\tuiArr= new Uint8Array(mx);\n\n\t\t\tfor(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);\n\n\t\t\treturn new myBlob([uiArr], {type: type});\n\t\t }\n\n\t\tfunction saver(url, winMode){\n\n\t\t\tif (\'download\' in anchor) { //html5 A[download]\n\t\t\t\tanchor.href = url;\n\t\t\t\tanchor.setAttribute("download", fileName);\n\t\t\t\tanchor.className = "download-js-link";\n\t\t\t\tanchor.innerHTML = "downloading...";\n\t\t\t\tanchor.style.display = "none";\n\t\t\t\tdocument.body.appendChild(anchor);\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tanchor.click();\n\t\t\t\t\tdocument.body.removeChild(anchor);\n\t\t\t\t\tif(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}\n\t\t\t\t}, 66);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// handle non-a[download] safari as best we can:\n\t\t\tif(/(Version)\\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari\\//.test(navigator.userAgent)) {\n\t\t\t\tif(/^data:/.test(url))\turl="data:"+url.replace(/^data:([\\w\\/\\-\\+]+)/, defaultMime);\n\t\t\t\tif(!window.open(url)){ // popup blocked, offer direct download:\n\t\t\t\t\tif(confirm("Displaying New Document\\n\\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t//do iframe dataURL download (old ch+FF):\n\t\t\tvar f = document.createElement("iframe");\n\t\t\tdocument.body.appendChild(f);\n\n\t\t\tif(!winMode && /^data:/.test(url)){ // force a mime that will download:\n\t\t\t\turl="data:"+url.replace(/^data:([\\w\\/\\-\\+]+)/, defaultMime);\n\t\t\t}\n\t\t\tf.src=url;\n\t\t\tsetTimeout(function(){ document.body.removeChild(f); }, 333);\n\n\t\t}//end saver\n\n\n\n\n\t\tif (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)\n\t\t\treturn navigator.msSaveBlob(blob, fileName);\n\t\t}\n\n\t\tif(self.URL){ // simple fast and modern way using Blob and URL:\n\t\t\tsaver(self.URL.createObjectURL(blob), true);\n\t\t}else{\n\t\t\t// handle non-Blob()+non-URL browsers:\n\t\t\tif(typeof blob === "string" || blob.constructor===toString ){\n\t\t\t\ttry{\n\t\t\t\t\treturn saver( "data:" + mimeType + ";base64," + self.btoa(blob) );\n\t\t\t\t}catch(y){\n\t\t\t\t\treturn saver( "data:" + mimeType + "," + encodeURIComponent(blob) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Blob but not URL support:\n\t\t\treader=new FileReader();\n\t\t\treader.onload=function(e){\n\t\t\t\tsaver(this.result);\n\t\t\t};\n\t\t\treader.readAsDataURL(blob);\n\t\t}\n\t\treturn true;\n\t}; /* end download() */\n}));\n',
],
names: [
"module",
"exports",
"download",
"data",
"strFileName",
"strMimeType",
"blob",
"reader",
"self",
"window",
"defaultMime",
"mimeType",
"payload",
"url",
"anchor",
"document",
"createElement",
"toString",
"a",
"String",
"myBlob",
"Blob",
"MozBlob",
"WebKitBlob",
"fileName",
"call",
"bind",
"this",
"length",
"split",
"pop",
"href",
"indexOf",
"ajax",
"XMLHttpRequest",
"open",
"responseType",
"onload",
"e",
"target",
"response",
"setTimeout",
"send",
"test",
"navigator",
"msSaveBlob",
"dataUrlToBlob",
"saver",
"type",
"i",
"tempUiArr",
"Uint8Array",
"mx",
"charCodeAt",
"strUrl",
"parts",
"binData",
"atob",
"decodeURIComponent",
"uiArr",
"winMode",
"setAttribute",
"className",
"innerHTML",
"style",
"display",
"body",
"appendChild",
"click",
"removeChild",
"URL",
"revokeObjectURL",
"userAgent",
"replace",
"confirm",
"location",
"f",
"src",
"createObjectURL",
"constructor",
"btoa",
"y",
"encodeURIComponent",
"FileReader",
"result",
"readAsDataURL",
],
mappings:
"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",
x_google_ignoreList: [0],
};
上面的file对象就是一个完成的source map
4.使用sourcemap包提供的方法,根据报错信息找到真正的报错行列,大概这样子
const consumer = await new sourceMap.SourceMapConsumer(file);
const lookup = {
file: "../../node_modules/downloadjs/download.js",
message: "Uncaught ReferenceError: data is not defined",
line: 1,
column: 200,
};
const result = consumer.originalPositionFor(lookup);
result返回
{
column: 26,
line: 25,
name: "data",
source: "../../node_modules/downloadjs/download.js"
}
最后效果
下面是完整代码
<!DOCTYPE html>
<head>
<script src="https://unpkg.com/source-map@0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm":
"https://unpkg.com/source-map@0.7.3/lib/mappings.wasm",
});
</script>
</head>
<html>
<div id="abc"></div>
<script>
const file = {
version: 3,
file: "downloadjs-legacy-b08799ac.js",
sources: ["../../node_modules/downloadjs/download.js"],
sourcesContent: [
'//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage\n// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime\n// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs\n// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.\n// v4 adds AMD/UMD, commonJS, and plain browser support\n// v4.1 adds url download capability via solo URL argument (same domain/CORS only)\n// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors\n// https://github.com/rndme/download\n\n(function (root, factory) {\n\tif (typeof define === \'function\' && define.amd) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([], factory);\n\t} else if (typeof exports === \'object\') {\n\t\t// Node. Does not work with strict CommonJS, but\n\t\t// only CommonJS-like environments that support module.exports,\n\t\t// like Node.\n\t\tmodule.exports = factory();\n\t} else {\n\t\t// Browser globals (root is window)\n\t\troot.download = factory();\n }\n}(this, function () {\n\n\treturn function download(data, strFileName, strMimeType) {\n\n\t\tvar self = window, // this script is only for browsers anyway...\n\t\t\tdefaultMime = "application/octet-stream", // this default mime also triggers iframe downloads\n\t\t\tmimeType = strMimeType || defaultMime,\n\t\t\tpayload = data,\n\t\t\turl = !strFileName && !strMimeType && payload,\n\t\t\tanchor = document.createElement("a"),\n\t\t\ttoString = function(a){return String(a);},\n\t\t\tmyBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),\n\t\t\tfileName = strFileName || "download",\n\t\t\tblob,\n\t\t\treader;\n\t\t\tmyBlob= myBlob.call ? myBlob.bind(self) : Blob ;\n\t \n\t\tif(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback\n\t\t\tpayload=[payload, mimeType];\n\t\t\tmimeType=payload[0];\n\t\t\tpayload=payload[1];\n\t\t}\n\n\n\t\tif(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument\n\t\t\tfileName = url.split("/").pop().split("?")[0];\n\t\t\tanchor.href = url; // assign href prop to temp anchor\n\t\t \tif(anchor.href.indexOf(url) !== -1){ // if the browser determines that it\'s a potentially valid url path:\n \t\tvar ajax=new XMLHttpRequest();\n \t\tajax.open( "GET", url, true);\n \t\tajax.responseType = \'blob\';\n \t\tajax.onload= function(e){ \n\t\t\t\t download(e.target.response, fileName, defaultMime);\n\t\t\t\t};\n \t\tsetTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:\n\t\t\t return ajax;\n\t\t\t} // end if valid url?\n\t\t} // end if url?\n\n\n\t\t//go ahead and download dataURLs right away\n\t\tif(/^data:([\\w+-]+\\/[\\w+.-]+)?[,;]/.test(payload)){\n\t\t\n\t\t\tif(payload.length > (1024*1024*1.999) && myBlob !== toString ){\n\t\t\t\tpayload=dataUrlToBlob(payload);\n\t\t\t\tmimeType=payload.type || defaultMime;\n\t\t\t}else{\t\t\t\n\t\t\t\treturn navigator.msSaveBlob ? // IE10 can\'t do a[download], only Blobs:\n\t\t\t\t\tnavigator.msSaveBlob(dataUrlToBlob(payload), fileName) :\n\t\t\t\t\tsaver(payload) ; // everyone else can save dataURLs un-processed\n\t\t\t}\n\t\t\t\n\t\t}else{//not data url, is it a string with special needs?\n\t\t\tif(/([\\x80-\\xff])/.test(payload)){\t\t\t \n\t\t\t\tvar i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;\n\t\t\t\tfor(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);\n\t\t\t \tpayload=new myBlob([tempUiArr], {type: mimeType});\n\t\t\t}\t\t \n\t\t}\n\t\tblob = payload instanceof myBlob ?\n\t\t\tpayload :\n\t\t\tnew myBlob([payload], {type: mimeType}) ;\n\n\n\t\tfunction dataUrlToBlob(strUrl) {\n\t\t\tvar parts= strUrl.split(/[:;,]/),\n\t\t\ttype= parts[1],\n\t\t\tdecoder= parts[2] == "base64" ? atob : decodeURIComponent,\n\t\t\tbinData= decoder( parts.pop() ),\n\t\t\tmx= binData.length,\n\t\t\ti= 0,\n\t\t\tuiArr= new Uint8Array(mx);\n\n\t\t\tfor(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);\n\n\t\t\treturn new myBlob([uiArr], {type: type});\n\t\t }\n\n\t\tfunction saver(url, winMode){\n\n\t\t\tif (\'download\' in anchor) { //html5 A[download]\n\t\t\t\tanchor.href = url;\n\t\t\t\tanchor.setAttribute("download", fileName);\n\t\t\t\tanchor.className = "download-js-link";\n\t\t\t\tanchor.innerHTML = "downloading...";\n\t\t\t\tanchor.style.display = "none";\n\t\t\t\tdocument.body.appendChild(anchor);\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tanchor.click();\n\t\t\t\t\tdocument.body.removeChild(anchor);\n\t\t\t\t\tif(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}\n\t\t\t\t}, 66);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// handle non-a[download] safari as best we can:\n\t\t\tif(/(Version)\\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari\\//.test(navigator.userAgent)) {\n\t\t\t\tif(/^data:/.test(url))\turl="data:"+url.replace(/^data:([\\w\\/\\-\\+]+)/, defaultMime);\n\t\t\t\tif(!window.open(url)){ // popup blocked, offer direct download:\n\t\t\t\t\tif(confirm("Displaying New Document\\n\\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t//do iframe dataURL download (old ch+FF):\n\t\t\tvar f = document.createElement("iframe");\n\t\t\tdocument.body.appendChild(f);\n\n\t\t\tif(!winMode && /^data:/.test(url)){ // force a mime that will download:\n\t\t\t\turl="data:"+url.replace(/^data:([\\w\\/\\-\\+]+)/, defaultMime);\n\t\t\t}\n\t\t\tf.src=url;\n\t\t\tsetTimeout(function(){ document.body.removeChild(f); }, 333);\n\n\t\t}//end saver\n\n\n\n\n\t\tif (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)\n\t\t\treturn navigator.msSaveBlob(blob, fileName);\n\t\t}\n\n\t\tif(self.URL){ // simple fast and modern way using Blob and URL:\n\t\t\tsaver(self.URL.createObjectURL(blob), true);\n\t\t}else{\n\t\t\t// handle non-Blob()+non-URL browsers:\n\t\t\tif(typeof blob === "string" || blob.constructor===toString ){\n\t\t\t\ttry{\n\t\t\t\t\treturn saver( "data:" + mimeType + ";base64," + self.btoa(blob) );\n\t\t\t\t}catch(y){\n\t\t\t\t\treturn saver( "data:" + mimeType + "," + encodeURIComponent(blob) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Blob but not URL support:\n\t\t\treader=new FileReader();\n\t\t\treader.onload=function(e){\n\t\t\t\tsaver(this.result);\n\t\t\t};\n\t\t\treader.readAsDataURL(blob);\n\t\t}\n\t\treturn true;\n\t}; /* end download() */\n}));\n',
],
names: [
"module",
"exports",
"download",
"data",
"strFileName",
"strMimeType",
"blob",
"reader",
"self",
"window",
"defaultMime",
"mimeType",
"payload",
"url",
"anchor",
"document",
"createElement",
"toString",
"a",
"String",
"myBlob",
"Blob",
"MozBlob",
"WebKitBlob",
"fileName",
"call",
"bind",
"this",
"length",
"split",
"pop",
"href",
"indexOf",
"ajax",
"XMLHttpRequest",
"open",
"responseType",
"onload",
"e",
"target",
"response",
"setTimeout",
"send",
"test",
"navigator",
"msSaveBlob",
"dataUrlToBlob",
"saver",
"type",
"i",
"tempUiArr",
"Uint8Array",
"mx",
"charCodeAt",
"strUrl",
"parts",
"binData",
"atob",
"decodeURIComponent",
"uiArr",
"winMode",
"setAttribute",
"className",
"innerHTML",
"style",
"display",
"body",
"appendChild",
"click",
"removeChild",
"URL",
"revokeObjectURL",
"userAgent",
"replace",
"confirm",
"location",
"f",
"src",
"createObjectURL",
"constructor",
"btoa",
"y",
"encodeURIComponent",
"FileReader",
"result",
"readAsDataURL",
],
mappings:
"kLAiBEA,EAAAC,QAOe,SAAAC,EAASC,EAAMC,EAAaC,GAE3C,IASCC,EACAC,EAVGC,EAAOC,OACVC,EAAc,2BACdC,EAAWN,GAAeK,EAC1BE,EAAUT,EACVU,GAAOT,IAAgBC,GAAeO,EACtCE,EAASC,SAASC,cAAc,KAChCC,EAAW,SAASC,GAAG,OAAOC,OAAOD,EAAG,EACxCE,EAAUZ,EAAKa,MAAQb,EAAKc,SAAWd,EAAKe,YAAcN,EAC1DO,EAAWpB,GAAe,WAY3B,GATCgB,EAAQA,EAAOK,KAAOL,EAAOM,KAAKlB,GAAQa,KAEzB,SAAfF,OAAOQ,QAEThB,GADAC,EAAQ,CAACA,EAASD,IACD,GACjBC,EAAQA,EAAQ,IAIdC,GAAOA,EAAIe,OAAQ,OACrBJ,EAAWX,EAAIgB,MAAM,KAAKC,MAAMD,MAAM,KAAK,GAC3Cf,EAAOiB,KAAOlB,GACqB,IAA9BC,EAAOiB,KAAKC,QAAQnB,IAAY,CAC9B,IAAIoB,EAAK,IAAIC,eAOhB,OANGD,EAAKE,KAAM,MAAOtB,GAAK,GACvBoB,EAAKG,aAAe,OACpBH,EAAKI,OAAQ,SAASC,GAC1BpC,EAASoC,EAAEC,OAAOC,SAAUhB,EAAUd,EAC5C,EACU+B,YAAW,WAAYR,EAAKS,MAAO,GAAG,GAClCT,CACV,CAKF,GAAG,iCAAiCU,KAAK/B,GAAS,CAEjD,KAAGA,EAAQgB,OAAU,aAAoBR,IAAWH,GAInD,OAAO2B,UAAUC,WAChBD,UAAUC,WAAWC,EAAclC,GAAUY,GAC7CuB,EAAMnC,GAJPD,GADAC,EAAQkC,EAAclC,IACLoC,MAAQtC,CAO7B,MACG,GAAG,gBAAgBiC,KAAK/B,GAAS,CAEhC,IADA,IAAIqC,EAAE,EAAGC,EAAW,IAAIC,WAAWvC,EAAQgB,QAASwB,EAAGF,EAAUtB,OAC3DqB,EAAEG,IAAKH,EAAGC,EAAUD,GAAIrC,EAAQyC,WAAWJ,GAChDrC,EAAQ,IAAIQ,EAAO,CAAC8B,GAAY,CAACF,KAAMrC,GACxC,CAOF,SAASmC,EAAcQ,GAStB,IARA,IAAIC,EAAOD,EAAOzB,MAAM,SACxBmB,EAAMO,EAAM,GAEZC,GADqB,UAAZD,EAAM,GAAiBE,KAAOC,oBACrBH,EAAMzB,OACxBsB,EAAII,EAAQ5B,OACZqB,EAAG,EACHU,EAAO,IAAIR,WAAWC,GAEhBH,EAAEG,IAAKH,EAAGU,EAAMV,GAAIO,EAAQH,WAAWJ,GAE7C,OAAO,IAAI7B,EAAO,CAACuC,GAAQ,CAACX,KAAMA,GACjC,CAEF,SAASD,EAAMlC,EAAK+C,GAEnB,GAAI,aAAc9C,EAYjB,OAXAA,EAAOiB,KAAOlB,EACdC,EAAO+C,aAAa,WAAYrC,GAChCV,EAAOgD,UAAY,mBACnBhD,EAAOiD,UAAY,iBACnBjD,EAAOkD,MAAMC,QAAU,OACvBlD,SAASmD,KAAKC,YAAYrD,GAC1B2B,YAAW,WACV3B,EAAOsD,QACPrD,SAASmD,KAAKG,YAAYvD,IACb,IAAV8C,GAAgBnB,YAAW,WAAYjC,EAAK8D,IAAIC,gBAAgBzD,EAAOiB,KAAM,GAAG,IACnF,GAAE,KACQ,EAIZ,GAAG,gDAAgDY,KAAKC,UAAU4B,WAKjE,MAJG,SAAS7B,KAAK9B,KAAMA,EAAI,QAAQA,EAAI4D,QAAQ,sBAAuB/D,IAClED,OAAO0B,KAAKtB,IACZ6D,QAAQ,oGAAoGC,SAAS5C,KAAKlB,IAEvH,EAIR,IAAI+D,EAAI7D,SAASC,cAAc,UAC/BD,SAASmD,KAAKC,YAAYS,IAEtBhB,GAAW,SAASjB,KAAK9B,KAC5BA,EAAI,QAAQA,EAAI4D,QAAQ,sBAAuB/D,IAEhDkE,EAAEC,IAAIhE,EACN4B,YAAW,WAAY1B,SAASmD,KAAKG,YAAYO,KAAO,IAExD,CAKD,GA5DAtE,EAAOM,aAAmBQ,EACzBR,EACA,IAAIQ,EAAO,CAACR,GAAU,CAACoC,KAAMrC,IA0D1BiC,UAAUC,WACb,OAAOD,UAAUC,WAAWvC,EAAMkB,GAGnC,GAAGhB,EAAK8D,IACPvB,EAAMvC,EAAK8D,IAAIQ,gBAAgBxE,IAAO,OAClC,CAEJ,GAAmB,iBAATA,GAAqBA,EAAKyE,cAAc9D,EACjD,IACC,OAAO8B,EAAO,QAAWpC,EAAa,WAAeH,EAAKwE,KAAK1E,GAC/D,CAAA,MAAM2E,GACN,OAAOlC,EAAO,QAAWpC,EAAa,IAAMuE,mBAAmB5E,GAC/D,EAIFC,EAAO,IAAI4E,YACJ9C,OAAO,SAASC,GACtBS,EAAMpB,KAAKyD,OACf,EACG7E,EAAO8E,cAAc/E,EACrB,CACD,OAAO,CACT",
x_google_ignoreList: [0],
};
const code = "";
window.onload = async function () {
const consumer = await new sourceMap.SourceMapConsumer(file);
const lookup = {
file: "../../node_modules/downloadjs/download.js",
message: "Uncaught ReferenceError: data is not defined",
line: 1,
column: 200,
};
const result = consumer.originalPositionFor(lookup);
const lines = consumer.sourcesContent[0].split("\n");
const { line, column } = result;
const showMaxLine = 5;
// 计算要展示的行的起始位置,起始行号不能小于1
const startLine = Math.max(1, line - Math.floor(showMaxLine / 2));
// 结束位置不能大于总行数
const endLine = Math.min(lines.length, startLine + showMaxLine - 1);
const showCode = lines
.slice(startLine - 1, endLine)
.map(
(v, idx) =>
`<div>
<span style="color: blue;padding-right:40px;">
${startLine + idx}
</span>
<span>
${
// 针对错误的行进行下划线+红色展示
idx + startLine === line
? "<span style='color: red'>" +
v.slice(0, column - 1) +
v.slice(column - 1) +
"</span>"
: v
}
</span>
</div>`
)
.join("\n");
document.querySelector("#abc").innerHTML = `
<div>
<span style="color: red">Uncaught ReferenceError: abc is not defined</span> in ${result.source} ${result.line}:${result.column}</div>
${showCode}`;
};
</script>
<body></body>
</html>