new Vue({ el: '#app', data() { return { props: { label: 'label', children: 'children' }, data: [], filterText: '', filterTextTime: null, popContent: '', dataObj: {} }; }, watch: { filterText(val) { clearTimeout(this.filterTextTime); this.filterTextTime = setTimeout(() => { if (val.length > 0 && val.length < 3) { return } this.$refs.tree.filter(val); }, 1000); } }, created() { let matched = location.href.match('demo=(.*)'); let file = `/callstack?file=data/data.js`; if (matched) { file = `/callstack?file=${matched[1]}`; } axios.get(file).then(response => { let txt = response.data; this.setData(txt, /gz$/.test(file)); }).catch(function (error) { console.log(error); }); }, methods: { setTextarea(f, fl) { const reader = new FileReader(); reader.onload = (event) => { this.setData(JSON.parse(event.target.result)); }; reader.readAsText(f.raw); }, async setData(dataObj, gz) { if (gz) { dataObj = await decompress(dataObj); dataObj = JSON.parse(dataObj) } let tempData = []; this.dataObj = dataObj; dataObj.ActionList.forEach((v2, idx) => { let secs = (v2[0][1] / 1e6).toFixed(6); let name = dataObj.FuncNameList[v2[0][3]]; let root = this.getRoot(v2[0][0], tempData); if (!root) { root = { label: name, children: [], secs: secs, idx: idx, }; tempData.push(root) } else { let depth = v2[0][2]; let lastChild = this.getChildren(depth, root); if (lastChild && lastChild.children) { lastChild.children.push({ label: name, children: [], secs: secs, idx: idx, }) } } }); this.data = tempData; }, filterNode(value, data) { if (!value) return true; return data.label.indexOf(value) !== -1; }, getRoot(rootId, rootList) { for (let i in rootList) { let currIdx = rootList[i].idx; if (this.dataObj.ActionList[currIdx][0][0] === rootId) { return rootList[i]; } } return null; }, getChildren(depth, data) { if (depth <= 1) { return data; } if (!data.children || data.children.length === 0) { return null; } let lastChild = data.children[data.children.length - 1]; return this.getChildren(depth - 1, lastChild); }, currentCopy(event) { let el = $(event.currentTarget).parents('.el-tree-node'); let str = '
' + getLines('', el.eq(0)) + ''; this.$alert(str, '', {dangerouslyUseHTMLString: true}); }, currentShow0(data) { let self = this; let v2 = self.dataObj.ActionList[data.idx]; let file = self.dataObj.FileList[v2[0][4]] + ":" + v2[0][5]; let ret = ""; let args = []; let eval = []; if (v2[0].length > 6) { ret = self.dataObj.FileList[v2[0][6]] + ":" + v2[0][7]; } if (v2[1]) { v2[1].forEach((v3) => { args.push(self.dataObj.FuncArgList[v3]) }) } if (v2[2]) { v2[2].forEach((v3) => { eval.push(self.dataObj.FuncArgList[v3]) }) } self.popContent = `Ret : ${ret}\nFile: ${file}\nArgs: ` + args.join(", ") + "\nEval: " + eval.join("\nEval: "); }, currentShow1(data) { let self = this; let v2 = self.dataObj.ActionList[data.idx]; let file = self.dataObj.FileList[v2[0][4]] + "#L" + v2[0][5]; openInVscode(file, function (err) { self.$message('请本地运行xgo'); }); }, currentShow2(data) { let self = this; let base = 'https://github.com'; let v2 = self.dataObj.ActionList[data.idx]; let file = self.dataObj.FileList[v2[0][4]] + "#L" + v2[0][5]; if (/\/go([\d.]*)\/src\//.test(file)) { let path = file.replace(/^.*\/go([\d.]+)\/src\//, '/golang/go/blob/go$1/src/'); path = path.replace(/^.*\/go\/src\//, '/golang/go/blob/go1.20.6/src/'); openGithub(base + path); } else if (file.includes("github.com")) { let path = file.replace(/^.*\/github.com/, '').replace('@', '/blob/'); openGithub(base + path); } else { let path = `
${escape(file)}
`; self.$alert(path, '', {dangerouslyUseHTMLString: true}); } } } }); function decompress(b64Data) { let strData = atob(b64Data); let charData = strData.split('').map(function (x) { return x.charCodeAt(0); }); let binData = new Uint8Array(charData); let cs = new DecompressionStream("gzip"); let writer = cs.writable.getWriter(); writer.write(binData); writer.close(); return new Response(cs.readable).arrayBuffer().then(function (arrayBuffer) { return new TextDecoder().decode(arrayBuffer); }); } function escape(a) { return a.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); } function getLines(pre, currNode) { let str = pre + '|-' + currNode.find('.el-tree-node__content .custom-label').html().replace(/^\s+|\s+$/g, '') + "\n"; let chi = currNode.find('> .el-tree-node__children > .el-tree-node'); chi.each(function (index, element) { if ($(element).parent().css('display') !== 'none') { str += getLines(pre + ' ', $(element)); } }); return str; } function openGithub(url) { const args = { target: url, style: "default", type: "code", showBorder: "on", showLineNumbers: "on", showFileMeta: "on", showFullPath: "on", showCopy: "on", }; window.open("/callstack?" + new URLSearchParams(args).toString()); } function openInVscode(fileStr, callback) { let arr = fileStr.split("#L"); if (arr.length < 2) { arr = [fileStr, '0']; } const args = { file: arr[0], line: Number(arr[1]) }; let str = "http://127.0.0.1:7070/openVscodeFile?" + new URLSearchParams(args).toString(); fetch(str, {'mode':'no-cors'}).then((data) => { console.log(data); }).catch((err) => { callback(err) }); }