添加检测任务模块及死锁检测bug修改
This commit is contained in:
parent
b93dfd7244
commit
1111d8d11b
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": ["dbaeumer.vscode-eslint", "amodio.tsl-problem-matcher"]
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "${defaultBuildTask}"
|
||||
},
|
||||
{
|
||||
"name": "Extension Tests",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js",
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "tasks: watch-tests"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.exclude": {
|
||||
"out": false, // set this to true to hide the "out" folder with the compiled JS files
|
||||
"dist": false // set this to true to hide the "dist" folder with the compiled JS files
|
||||
},
|
||||
"search.exclude": {
|
||||
"out": true, // set this to false to include "out" folder in search results
|
||||
"dist": true // set this to false to include "dist" folder in search results
|
||||
},
|
||||
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
|
||||
"typescript.tsc.autoDetect": "off"
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$ts-webpack-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never",
|
||||
"group": "watchers"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch-tests",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never",
|
||||
"group": "watchers"
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "tasks: watch-tests",
|
||||
"dependsOn": [
|
||||
"npm: watch",
|
||||
"npm: watch-tests"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
# sudo apt install sshpass
|
||||
cd view-ui
|
||||
npm install
|
||||
npm run build
|
||||
rm -rf ../detect-plugin/dist/
|
||||
cp dist/ ../detect-plugin/ -r
|
||||
cd ../detect-plugin
|
||||
yarn
|
||||
vsce package
|
|
@ -0,0 +1,26 @@
|
|||
# C/C++ 程序锁分析
|
||||
#### [仓库](https://gitee.com/openkylin/deadlock-detect)
|
||||
|
||||
## 介绍
|
||||
|
||||
deadlock-detect 是一款基于OpenKylin社区kylin-code的拓展插件,用于C/C++程序的死锁检测及锁状态分析,帮助开发者在Linux系统下识别多线程死锁状态、互斥锁自旋锁等状态异常问题,并对程序加锁位置分析。
|
||||
|
||||
---
|
||||
|
||||
## 功能
|
||||
- C/C++ 多线程序锁分析
|
||||
- 可视化观察临界区进入次数、耗时、条件变量等待时长
|
||||
- 线程退出未释放锁异常
|
||||
- 可执行程序死锁检测
|
||||
- 进程死锁检测
|
||||
- 远程环境进程死锁检测
|
||||
|
||||
## 使用方法
|
||||
1. C/C++ 多线程序锁分析
|
||||
|
||||
|
||||
|
||||
2. 进程死锁检测
|
||||
|
||||
|
||||
3. 远程进程死锁检测
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/bash
|
||||
ARCH=`arch`
|
||||
|
||||
DIR=`dirname $0`
|
||||
BINLOADER=$DIR/${ARCH}/binloader
|
||||
|
||||
if [ $# -lt 1 ];then
|
||||
# echo "Error params"
|
||||
exit 101
|
||||
fi
|
||||
|
||||
BINPATH=$1
|
||||
if [ ! -e ${BINPATH} ] || [ "a" == "a${BINPATH}" ];then
|
||||
# echo "No File"
|
||||
exit 102
|
||||
fi
|
||||
|
||||
if [ -z "`file ${BINPATH} | grep ELF`" ];then
|
||||
# echo "Not ELF"
|
||||
exit 103
|
||||
fi
|
||||
|
||||
LIBPTHREAD_PATH=`ldd ${BINPATH} | grep pthread | awk '{print $3}'`
|
||||
if [ -z "${LIBPTHREAD_PATH}" ];then
|
||||
# echo "No pthread"
|
||||
exit 104
|
||||
fi
|
||||
|
||||
${BINLOADER} $@
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -16,15 +16,50 @@
|
|||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onCommand:deadlock-detect.detect"
|
||||
"onCommand:deadlock-detect.open",
|
||||
"onLanguage:c",
|
||||
"onLanguage:cpp",
|
||||
"onCommand:workbench.action.tasks.runTask"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "deadlock-detect.detect",
|
||||
"command": "deadlock-detect.open",
|
||||
"title": "C/C++程序死锁检测"
|
||||
}
|
||||
],
|
||||
"taskDefinitions": [
|
||||
{
|
||||
"type": "deadlockdetect",
|
||||
"required": [
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%deadlockdetect.taskDefinitions.command.description%"
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "%deadlockdetect.taskDefinitions.args.description%"
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "%deadlockdetect.taskDefinitions.options.description%",
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string",
|
||||
"description": "%deadlockdetect.taskDefinitions.options.cwd.description%"
|
||||
},
|
||||
"env": {
|
||||
"type": "array",
|
||||
"description": "%deadlockdetect.taskDefinitions.options.env.description%"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -39,19 +74,22 @@
|
|||
"test": "node ./out/test/runTest.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.54.0",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "16.x",
|
||||
"@types/vscode": "^1.54.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
||||
"@typescript-eslint/parser": "^5.31.0",
|
||||
"@vscode/test-electron": "^2.1.5",
|
||||
"eslint": "^8.20.0",
|
||||
"glob": "^8.0.3",
|
||||
"mocha": "^10.0.0",
|
||||
"typescript": "^4.7.4",
|
||||
"ts-loader": "^9.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"@vscode/test-electron": "^2.1.5"
|
||||
"webpack-cli": "^4.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^2.1.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"deadlockdetect.taskDefinitions.command.description": "这里是要检测的可执行程序(必选) 相对路径或绝对路径",
|
||||
"deadlockdetect.taskDefinitions.args.description": "这里是可执行程序的参数(可选)",
|
||||
"deadlockdetect.taskDefinitions.options.description": "这里是一些可选型",
|
||||
"deadlockdetect.taskDefinitions.options.cwd.description": "程序的运行目录",
|
||||
"deadlockdetect.taskDefinitions.options.env.description": "程序的环境变量"
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
import * as vscode from 'vscode';
|
||||
import * as child from 'child_process';
|
||||
import {execDetect, testPwd, prase_yaml2html} from './utils';
|
||||
import { dirname, join } from 'path';
|
||||
import { kill } from 'process';
|
||||
import * as fs from 'fs';
|
||||
|
||||
type Options = {
|
||||
cwd?: string;
|
||||
env?: string[];
|
||||
};
|
||||
|
||||
|
||||
const binLoader: string = join(dirname(__dirname), "detect-tools/bincheck_loader.sh");
|
||||
|
||||
interface DetectTaskDefinition extends vscode.TaskDefinition {
|
||||
command: string;
|
||||
args?: string[];
|
||||
options?: Options;
|
||||
}
|
||||
|
||||
|
||||
export class DetectTaskProvider implements vscode.TaskProvider {
|
||||
static customBuildScriptType = 'deadlockdetect';
|
||||
private tasks: vscode.Task[] | undefined;
|
||||
|
||||
private sharedState: string | undefined;
|
||||
private cmd: child.ChildProcessWithoutNullStreams | undefined;
|
||||
constructor(private workspaceRoot: string, private context: vscode.ExtensionContext) { }
|
||||
|
||||
public async provideTasks(): Promise<vscode.Task[]> {
|
||||
return this.getTasks();
|
||||
}
|
||||
|
||||
public resolveTask(_task: vscode.Task): vscode.Task | undefined {
|
||||
const command: string = _task.definition.command;
|
||||
if (command) {
|
||||
const definition: DetectTaskDefinition = <any>_task.definition;
|
||||
return this.getTask(definition.command, definition.args ? definition.args : [], definition.options ? definition.options : {}, definition);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private getTasks(): vscode.Task[] {
|
||||
if (this.tasks !== undefined) {
|
||||
return this.tasks;
|
||||
}
|
||||
this.tasks = [];
|
||||
var option: Options = {
|
||||
env: ["程序执行所需额外环境变量:如 DISPALY=1"],
|
||||
};
|
||||
this.tasks!.push(this.getTask("被检测可执行程序", ["可执行程序参数(可选)"], option));
|
||||
return this.tasks;
|
||||
}
|
||||
|
||||
private getTask(command: string, args: string[], option: Options, definition?: DetectTaskDefinition): vscode.Task {
|
||||
if (definition === undefined) {
|
||||
definition = {
|
||||
type: DetectTaskProvider.customBuildScriptType,
|
||||
command: command,
|
||||
args: args,
|
||||
options: option,
|
||||
};
|
||||
}
|
||||
return new vscode.Task(definition, vscode.TaskScope.Workspace, "可执行程序锁检测",
|
||||
DetectTaskProvider.customBuildScriptType, new vscode.CustomExecution(async (): Promise<vscode.Pseudoterminal> => {
|
||||
// When the task is executed, this callback will run. Here, we setup for running the task.
|
||||
return new CustomBuildTaskTerminal(this.cmd, this.context, command, args, option, () => this.sharedState, (state: string) => this.sharedState = state);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
|
||||
private writeEmitter = new vscode.EventEmitter<string>();
|
||||
onDidWrite: vscode.Event<string> = this.writeEmitter.event;
|
||||
private closeEmitter = new vscode.EventEmitter<number>();
|
||||
onDidClose?: vscode.Event<number> = this.closeEmitter.event;
|
||||
private passwd: string | undefined;
|
||||
private checkedPid: number = 0;
|
||||
constructor(private cmd: child.ChildProcessWithoutNullStreams | undefined, private context: vscode.ExtensionContext, private command: string, private args: string[], private option: Options, private getSharedState: () => string | undefined, private setSharedState: (state: string) => void) {
|
||||
}
|
||||
|
||||
open(initialDimensions: vscode.TerminalDimensions | undefined): void {
|
||||
// At this point we can start using the terminal.
|
||||
if (this.command.length) {
|
||||
let found = false;
|
||||
vscode.workspace.workspaceFolders?.forEach((value)=>{
|
||||
// value.uri.fsPath
|
||||
if(this.command[0] == '/' && !found){
|
||||
this.option.cwd = value.uri.fsPath;
|
||||
found = true;
|
||||
}
|
||||
if(!found){
|
||||
let absPath = join(value.uri.fsPath, this.command);
|
||||
if(fs.existsSync(absPath)){
|
||||
this.option.cwd = value.uri.fsPath;
|
||||
this.command = absPath;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if(!found || !fs.existsSync(this.command)){
|
||||
vscode.window.showWarningMessage("未找到被检测二进制文件, 请输入相对路径或绝对路径");
|
||||
this.closeEmitter.fire(0);
|
||||
return;
|
||||
}
|
||||
// vscode.workspace.workspaceFolders
|
||||
vscode.window.showInputBox({
|
||||
password:true, // 输入内容是否是密码
|
||||
ignoreFocusOut:true, // 默认false,设置为true时鼠标点击别的地方输入框不会消失
|
||||
placeHolder:'请输入用户密码', // 在输入框内的提示信息
|
||||
prompt:'请输入当前用户的密码',
|
||||
}).then((pwd)=>{
|
||||
if(pwd === undefined || pwd?.length === 0)
|
||||
{
|
||||
this.closeEmitter.fire(0);
|
||||
return;
|
||||
}
|
||||
testPwd(pwd, (ok)=>{
|
||||
if(ok){
|
||||
this.passwd = pwd;
|
||||
this.doExec();
|
||||
return;
|
||||
}
|
||||
vscode.window.showErrorMessage("用户密码不匹配");
|
||||
this.closeEmitter.fire(0);
|
||||
});
|
||||
});
|
||||
}else{
|
||||
vscode.window.showWarningMessage("未发现被检测二进制文件");
|
||||
this.closeEmitter.fire(0);
|
||||
}
|
||||
}
|
||||
close(): void {
|
||||
if(this.cmd){
|
||||
kill(this.checkedPid, 9);
|
||||
vscode.window.showWarningMessage("检测任务已退出");
|
||||
}
|
||||
}
|
||||
|
||||
// 开始执行待检测程序
|
||||
private async doExec(): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
this.writeEmitter.fire('正在检测 ...\r\n');
|
||||
this.option.env?.forEach(e =>{
|
||||
let kv = e.split('=', 2);
|
||||
if(kv.length === 2){
|
||||
process.env[kv[0]] = kv[1];
|
||||
}
|
||||
});
|
||||
let hadPid = false;
|
||||
let coption: child.SpawnOptionsWithoutStdio = {
|
||||
env: process.env
|
||||
};
|
||||
if(this.option.cwd?.length){
|
||||
coption.cwd = this.option.cwd;
|
||||
}
|
||||
this.cmd = child.spawn(binLoader, [this.command, ...this.args], coption);
|
||||
this.cmd.on('error', (err)=>{
|
||||
this.writeEmitter.fire('执行失败 ... ' + err.message);
|
||||
});
|
||||
this.cmd.on('exit', (code) =>{
|
||||
let errmsg = "";
|
||||
switch (code) {
|
||||
case 101:
|
||||
errmsg = "待检测可执行程序不能为空 !";
|
||||
break;
|
||||
case 102:
|
||||
errmsg = "待检测可执行程序未找到,请确认可执行程序路径是否存在 !";
|
||||
break;
|
||||
case 103:
|
||||
errmsg = "待检测可执行程序不是二进制文件 !";
|
||||
break;
|
||||
case 104:
|
||||
errmsg = "待检测可执行程序未引用pthread动态库 !";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(errmsg.length){
|
||||
vscode.window.showErrorMessage(errmsg);
|
||||
}
|
||||
this.writeEmitter.fire('被检测程序已终止 ... \r\n');
|
||||
const date = new Date();
|
||||
this.setSharedState(date.toTimeString() + ' ' + date.toDateString());
|
||||
this.closeEmitter.fire(0);
|
||||
resolve();
|
||||
});
|
||||
|
||||
this.cmd.stdout.on('data', (data) =>{
|
||||
// childPid: 17558
|
||||
let buff: Buffer = data;
|
||||
let str: string = buff.toString('utf8');
|
||||
let arrStr = str.split(/\r?\n/);
|
||||
arrStr.forEach((s)=>{
|
||||
this.writeEmitter.fire(s+'\r\n');
|
||||
});
|
||||
});
|
||||
this.cmd.stderr.on('data', (data) =>{
|
||||
let buff: Buffer = data;
|
||||
let str: string = buff.toString('utf8');
|
||||
if(!hadPid){
|
||||
let result = str.split("|");
|
||||
if(result.length >= 4){
|
||||
hadPid = true;
|
||||
this.checkedPid = parseInt(result[3].trim());
|
||||
execDetect(this.passwd, result[1].trim(), this.checkedPid, (detectResult)=>{
|
||||
if(detectResult.match(/fatal/)?.length){
|
||||
vscode.window.showWarningMessage("被检测程序存在严重问题!")
|
||||
}else if(detectResult.match(/deadlock/)?.length){
|
||||
vscode.window.showWarningMessage("被检测程序存在死锁!");
|
||||
}
|
||||
if(detectResult.match(/normal|fatal|deadlock/)?.length){
|
||||
const webPanel = vscode.window.createWebviewPanel(
|
||||
'detectResultWebview',
|
||||
"检测结果",
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
}
|
||||
)
|
||||
webPanel.webview.html = prase_yaml2html(this.command, this.context.extensionPath, webPanel.webview, detectResult);
|
||||
}else{
|
||||
vscode.window.showInformationMessage("程序已退出,但未检测到相关锁信息");
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
let arrStr = str.split(/\r?\n/);
|
||||
arrStr.forEach((s)=>{
|
||||
this.writeEmitter.fire(s+'\r\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -3,9 +3,17 @@
|
|||
import * as vscode from 'vscode';
|
||||
import path = require('path');
|
||||
import fs = require("fs");
|
||||
import {DetectTaskProvider} from './detectTaskProvider';
|
||||
import { homedir } from 'os';
|
||||
|
||||
// linux命令操作模块
|
||||
var child = require('child_process');
|
||||
const { pid } = require('process');
|
||||
|
||||
let detectTaskProvider: vscode.Disposable | undefined;
|
||||
|
||||
function getWebViewContent(context: vscode.ExtensionContext, templatePath: string) {
|
||||
const resourcePath = path.join(context.extensionPath, templatePath);
|
||||
const resourcePath = path.join(path.dirname(__dirname), templatePath);
|
||||
const dirPath = path.dirname(resourcePath);
|
||||
let html = fs.readFileSync(resourcePath, 'utf-8');
|
||||
// vscode不支持直接加载本地资源,需要替换成其专有路径格式,这里只是简单的将样式和JS的路径替换
|
||||
|
@ -18,6 +26,23 @@ function getWebViewContent(context: vscode.ExtensionContext, templatePath: strin
|
|||
return html;
|
||||
}
|
||||
|
||||
function is_pid_exist(pid: string) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
child.exec(`ps -ef`, (e: any, x: string, c: any) => {
|
||||
if(e){
|
||||
reject('ps命令执行错误!')
|
||||
}else{
|
||||
let search=new RegExp("\\s+"+pid+"\\s+");
|
||||
let exist=search.test(x);
|
||||
if(exist){
|
||||
resolve('1');
|
||||
}else{
|
||||
resolve('-1');
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
|
@ -26,10 +51,155 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "deadlock-detect" is now active!');
|
||||
|
||||
let newFn={
|
||||
local_detect_deadlock:function (message: any ,panel: vscode.WebviewPanel){
|
||||
let form=message.form;
|
||||
|
||||
if(form.CmdType==1){
|
||||
|
||||
child.exec(`echo '${form.pwd}' | sudo -S ps`, (e: any, x: string, c: any) => {
|
||||
if(e){
|
||||
form.success='error-pwd';
|
||||
form.msg='您输入的密码错误!';
|
||||
if(e.message.indexOf('sudoers')!=-1){
|
||||
form.msg='当前用户无sudo权限,请在拥有sudo权限后重试!';
|
||||
}
|
||||
panel.webview.postMessage({
|
||||
res: form
|
||||
})
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
let pid_exist = is_pid_exist(form.pid);
|
||||
pid_exist.then((result)=>{
|
||||
console.log(result);
|
||||
if(result=='-1'){
|
||||
form.success='error-pid';
|
||||
form.msg='进程号不存在,请重新输入';
|
||||
panel.webview.postMessage({
|
||||
res: form
|
||||
})
|
||||
return
|
||||
}else if(result=='1'){
|
||||
child.exec(`echo '${form.pwd}' | sudo -S ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`, (e: any, x: string, c: any) => {
|
||||
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
|
||||
if(!e){
|
||||
form.data =x;
|
||||
form.success='success';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
}
|
||||
else{
|
||||
form.success='error';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
remote_detect_deadlock:function (message: any ,panel: vscode.WebviewPanel){
|
||||
let form=message.form;
|
||||
|
||||
if(form.CmdType==3){
|
||||
// sudo apt install sshpass
|
||||
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip}`, (e: any, x: string, c: any) => {
|
||||
if(e){
|
||||
form.success='error-ssh-login';
|
||||
form.msg='无法登录您指定的远端系统,请确保具有ssh登录权限!';
|
||||
panel.webview.postMessage({
|
||||
res: form
|
||||
})
|
||||
return;
|
||||
}
|
||||
})
|
||||
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ps'`, (e: any, x: string, c: any) => {
|
||||
if(e){
|
||||
form.success='error-not-sudoer';
|
||||
form.msg='user is not sudoer!';
|
||||
if(e.message.indexOf('sudoers')!=-1){
|
||||
form.msg='当前用户无sudo权限,请在拥有sudo权限后重试!';
|
||||
}
|
||||
panel.webview.postMessage({
|
||||
res: form
|
||||
})
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
let pid_exist = new Promise(function(resolve, reject) {
|
||||
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ps -ef'`, (e: any, x: string, c: any) => {
|
||||
if(e){
|
||||
reject('ps命令执行错误!')
|
||||
}else{
|
||||
let search=new RegExp("\\s+"+form.pid+"\\s+");
|
||||
let exist=search.test(x);
|
||||
if(exist){
|
||||
resolve('1');
|
||||
}else{
|
||||
resolve('-1');
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
pid_exist.then((result)=>{
|
||||
console.log(result);
|
||||
if(result=='-1'){
|
||||
form.success='error-pid';
|
||||
form.msg='进程号不存在,请重新输入';
|
||||
panel.webview.postMessage({
|
||||
res: form
|
||||
})
|
||||
return;
|
||||
}else if(result=='1'){
|
||||
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} '[ ! -d .deadlock-detect ] && mkdir .deadlock-detect || ls .deadlock-detect'`, (e: any, x: string, c: any) => {
|
||||
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
|
||||
if(e){
|
||||
form.success='error-mkdir';
|
||||
form.msg='创建目录.deadlock-detect失败!';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
});
|
||||
child.exec(`sshpass -p '${form.pwd}' scp -o StrictHostKeyChecking=no ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.user}@${form.ip}:./.deadlock-detect`, (e: any, x: string, c: any) => {
|
||||
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
|
||||
if(e){
|
||||
form.success='error-scp';
|
||||
form.msg='scp EXE failed!';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
});
|
||||
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ./.deadlock-detect/detect_deadlock ${form.pid}'`, (e: any, x: string, c: any) => {
|
||||
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
|
||||
if(!e){
|
||||
form.data =x;
|
||||
console.log(x);
|
||||
form.success='success';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
}
|
||||
else{
|
||||
form.success='error';
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
// The command has been defined in the package.json file
|
||||
// Now provide the implementation of the command with registerCommand
|
||||
// The commandId parameter must match the command field in package.json
|
||||
let disposable = vscode.commands.registerCommand('deadlock-detect.detect', () => {
|
||||
let disposable = vscode.commands.registerCommand('deadlock-detect.open', () => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
// Display a message box to the user
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
|
@ -38,14 +208,31 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: false,
|
||||
retainContextWhenHidden: true,
|
||||
}
|
||||
);
|
||||
panel.webview.html = getWebViewContent(context, "./dist/index.html");
|
||||
|
||||
panel.webview.onDidReceiveMessage(message => {
|
||||
switch(message.form.CmdType) {
|
||||
case 1://local pid dead-detect
|
||||
newFn.local_detect_deadlock(message,panel);
|
||||
break;
|
||||
case 3://remote pid dead-detect
|
||||
newFn.remote_detect_deadlock(message,panel);
|
||||
break;
|
||||
}
|
||||
});
|
||||
panel.webview.html = getWebViewContent(context, 'dist/index.html');
|
||||
});
|
||||
|
||||
const workspaceRoot = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) ? vscode.workspace.workspaceFolders[0].uri.fsPath : homedir();
|
||||
detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context));
|
||||
context.subscriptions.push(disposable);
|
||||
}
|
||||
|
||||
// this method is called when your extension is deactivated
|
||||
export function deactivate() {}
|
||||
export function deactivate() {
|
||||
if(detectTaskProvider){
|
||||
detectTaskProvider.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,421 @@
|
|||
import * as child from 'child_process';
|
||||
import * as vscode from 'vscode';
|
||||
import { dirname, join } from 'path';
|
||||
import * as YAML from 'yaml';
|
||||
|
||||
const archs = new Map([
|
||||
["x86_64", "x86_64"],
|
||||
["x64", "x86_64"],
|
||||
["arm64", "arm64"]
|
||||
]);
|
||||
|
||||
const myArch = archs.get(process.arch);
|
||||
const detectTool: string = join(dirname(__dirname), "detect-tools", myArch ? myArch: "x86_64", "deadlockcheck");
|
||||
|
||||
export function execDetect(pwd: string | undefined, libPthreadPath: string, checkedPid: number, cb: (da:string)=> void) {
|
||||
var task = child.exec(`echo ${pwd} | sudo -S ${detectTool} --threadlib ${libPthreadPath} --pid ${checkedPid}`, (err, out, e)=>{
|
||||
if(err?.message){
|
||||
vscode.window.showErrorMessage('附加到被检测程序失败, '+err.message);
|
||||
return;
|
||||
}
|
||||
if(out.length){
|
||||
cb(out);
|
||||
}
|
||||
child.exec(`sudo -k`);
|
||||
});
|
||||
}
|
||||
|
||||
export function testPwd(pwd:string, cb: (ok: boolean)=>void): void {
|
||||
if(pwd?.length){
|
||||
child.exec(`echo ${pwd} | sudo -S echo okok`, (err, stdout, stderr)=>{
|
||||
if(stdout.includes('okok')){
|
||||
child.exec(`sudo -k`, (e1, stdout1, stderr3)=>{
|
||||
cb(true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
cb(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function circledNodesPosition(x:number, y: number, index: number, nodesLen: number) {
|
||||
const avd = 360 / nodesLen;
|
||||
const ahd = avd * Math.PI / 180;
|
||||
return {
|
||||
x: Math.sin((ahd * index)) * 15 + x,
|
||||
y: Math.cos((ahd * index)) * 15 + y
|
||||
}
|
||||
}
|
||||
|
||||
// warn: "process exit"
|
||||
// normalInfo:
|
||||
// mutex:
|
||||
// - pid: 12619
|
||||
// details:
|
||||
// 0x7f6a92f4c990: 5-7673-0
|
||||
// 0x7f6a92f4c968: 1-3764-0
|
||||
// 0x7ffc74e6ab98: 1-7411-0
|
||||
// totalTime: 18848
|
||||
// condWaitTime: 0
|
||||
// - pid: 12618
|
||||
// details:
|
||||
// 0x7f6a92f4c990: 6-10005-0
|
||||
// 0x7f6a92f4c968: 1-95491-0
|
||||
// 0x7ffc74e6ab98: 2-43556-8000086897
|
||||
// totalTime: 149052
|
||||
// condWaitTime: 8000086897
|
||||
// - pid: 12560
|
||||
// details:
|
||||
// 0x7f6a92f4c968: 2-36323-0
|
||||
// totalTime: 36323
|
||||
// condWaitTime: 0
|
||||
|
||||
// 输出死锁时的信息
|
||||
function product_deadlockinfo_to_html(cmd: string, echartsPath: string, deadlockDesc: string, nodesInfo: object[], linksInfo: object[]) {
|
||||
let _nodesInfo = JSON.stringify(nodesInfo);
|
||||
let _linksInfo = JSON.stringify(linksInfo);
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" style="height: 100%">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="height: 100%; margin: 0">
|
||||
<div id="deadlockinfo" style="width:60%;margin:auto">
|
||||
<h3>
|
||||
被测程序
|
||||
</h3>
|
||||
<p>${cmd}</p>
|
||||
<h3>
|
||||
死锁关系描述
|
||||
</h3>
|
||||
<ul>
|
||||
${deadlockDesc}
|
||||
</ul>
|
||||
</div>
|
||||
<br><br>
|
||||
<div id="container" style="height: 70%;width:60%;margin:auto"></div>
|
||||
<script type="text/javascript" src="${echartsPath}"></script>
|
||||
<script type="text/javascript">
|
||||
var dom = document.getElementById('container');
|
||||
var myChart = echarts.init(dom, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
var app = {};
|
||||
|
||||
var option;
|
||||
|
||||
option = {
|
||||
title: {
|
||||
text: '死锁关系图'
|
||||
},
|
||||
tooltip: {},
|
||||
animationDurationUpdate: 1500,
|
||||
animationEasingUpdate: 'quinticInOut',
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
layout: 'none',
|
||||
roam: true,
|
||||
symbolSize: 80,
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
edgeSymbol: ['none', 'arrow'],
|
||||
edgeSymbolSize: [4, 10],
|
||||
edgeLabel: {
|
||||
normal: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
fontSize: 8
|
||||
},
|
||||
formatter: "{c}"
|
||||
}
|
||||
},
|
||||
data: ${_nodesInfo},
|
||||
links: ${_linksInfo},
|
||||
lineStyle: {
|
||||
opacity: 0.9,
|
||||
width: 2,
|
||||
curveness: -0.1
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
if (option && typeof option === 'object') {
|
||||
myChart.setOption(option);
|
||||
}
|
||||
window.addEventListener('resize', myChart.resize);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
|
||||
// 输入正常锁信息的html
|
||||
function product_normalinfo_to_html(cmd: string, echartsPath: string, mutexInfo:string, dimensionsList: string[], sourceList: object[], seriesList: object[]) {
|
||||
let _dimensionsList = JSON.stringify(dimensionsList);
|
||||
let _sourceList = JSON.stringify(sourceList);
|
||||
let _seriesList = JSON.stringify(seriesList);
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" style="height: 55%">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="height: 100%; margin: 0">
|
||||
<br><br>
|
||||
<div style="width:60%;margin:auto">
|
||||
<h3>
|
||||
被测程序
|
||||
</h3>
|
||||
<p>${cmd}</p>
|
||||
<h3>各线程锁信息</h3>
|
||||
<ul>
|
||||
${mutexInfo}
|
||||
</ul>
|
||||
</div>
|
||||
<br><br><br>
|
||||
<div id="container" style="height: 100%;width:60%;margin:auto"></div>
|
||||
<script type="text/javascript" src="${echartsPath}"></script>
|
||||
<script type="text/javascript">
|
||||
var dom = document.getElementById('container');
|
||||
var myChart = echarts.init(dom, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
var app = {};
|
||||
var option;
|
||||
option = {
|
||||
title: {
|
||||
text: '临界区耗时'
|
||||
},
|
||||
legend: {},
|
||||
tooltip: {},
|
||||
dataset: {
|
||||
dimensions: ${_dimensionsList},
|
||||
source: ${_sourceList}
|
||||
},
|
||||
xAxis: { type: 'category' },
|
||||
yAxis: {},
|
||||
// Declare several bar series, each will be mapped
|
||||
// to a column of dataset.source by default.
|
||||
series: ${_seriesList}
|
||||
};
|
||||
if (option && typeof option === 'object') {
|
||||
myChart.setOption(option);
|
||||
}
|
||||
window.addEventListener('resize', myChart.resize);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
|
||||
// 线程退出但是未释放锁
|
||||
// fatal:
|
||||
// - pid: 23773
|
||||
// mutexes:
|
||||
// - 0x7ffd08d622d8
|
||||
// 输出线程退出但是未释放锁的html
|
||||
function product_fatalinfo_to_html(cmd: string, fatalInfo:string) {
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" style="height: 55%">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="height: 100%; margin: 0">
|
||||
<br><br>
|
||||
<div style="height: 100%;width:60%;margin:auto">
|
||||
<h3>
|
||||
被测程序
|
||||
</h3>
|
||||
<p>${cmd}</p>
|
||||
<h3>严重问题</h3>
|
||||
<ul>
|
||||
${fatalInfo}
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
|
||||
// 发生死锁
|
||||
// deadlock:
|
||||
// cycle:
|
||||
// - 0x7ffdd4f33b50
|
||||
// - 0x7ffdd4f33b28
|
||||
// threadid:
|
||||
// - 23446
|
||||
// - 23445
|
||||
|
||||
interface DetailInfo {
|
||||
[key:string]: string
|
||||
}
|
||||
|
||||
interface MutexInfo{
|
||||
pid: number,
|
||||
details: DetailInfo,
|
||||
totalTime: number,
|
||||
condWaitTime: number
|
||||
}
|
||||
|
||||
interface DeadlockInfo{
|
||||
cycle: number [],
|
||||
threadid: number[]
|
||||
}
|
||||
|
||||
interface FatalInfo{
|
||||
pid: number,
|
||||
mutexes: number[]
|
||||
}
|
||||
|
||||
interface SourceInfo {
|
||||
[key:string]: any
|
||||
};
|
||||
|
||||
function parse_mutexInfo(mutexObj:MutexInfo[], sinfoList:SourceInfo[], dimensionsList:string[], seriesList: object[]):string {
|
||||
let miStr: string = ``;
|
||||
let mutexSet = new Set<string>();
|
||||
mutexObj.forEach(obj =>{
|
||||
let sinfo:SourceInfo = {};
|
||||
sinfo['product'] = `线程 ${obj.pid}`;
|
||||
if(obj.condWaitTime){
|
||||
miStr += `
|
||||
<li>线程 ${obj.pid} 临界区共耗时 ${obj.totalTime} 纳秒 其中条件变量等待时间 ${obj.condWaitTime} 纳秒.
|
||||
<ul>
|
||||
`;
|
||||
}else{
|
||||
miStr += `
|
||||
<li>线程 ${obj.pid} 临界区共耗时 ${obj.totalTime} 纳秒.
|
||||
<ul>
|
||||
`;
|
||||
}
|
||||
for (const key1 in obj.details) {
|
||||
let info = obj.details[key1].split('-');
|
||||
if(info.length >= 3){
|
||||
let key = '互斥量 0x'+Number(key1).toString(16);
|
||||
sinfo[key] = Number(info[1]);
|
||||
mutexSet.add(key);
|
||||
if(Number(info[2])){
|
||||
miStr += `
|
||||
<li>
|
||||
进入互斥量(${key})保护的临界区 ${info[0]} 次, 共耗时 ${info[1]} 纳秒, 条件变量等待 ${info[2]} 纳秒.
|
||||
</li>
|
||||
`
|
||||
}else{
|
||||
miStr += `
|
||||
<li>
|
||||
进入互斥量(${key})保护的临界区 ${info[0]} 次, 共耗时 ${info[1]} 纳秒.
|
||||
</li>
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
miStr += `
|
||||
</ul>
|
||||
</li>
|
||||
`
|
||||
sinfoList.push(sinfo);
|
||||
});
|
||||
dimensionsList.push('product');
|
||||
mutexSet.forEach((mutex)=>{
|
||||
dimensionsList.push(mutex);
|
||||
});
|
||||
for (let index = 0; index < sinfoList.length; index++) {
|
||||
seriesList.push({type:'bar'});
|
||||
}
|
||||
return miStr;
|
||||
}
|
||||
|
||||
function parse_fatalInfo(fatalInfoList:FatalInfo[]) {
|
||||
let fatalStr =``;
|
||||
fatalInfoList.forEach(fatal=>{
|
||||
fatalStr += `
|
||||
<li> 线程 ${fatal.pid} 已退出, 但以下互斥量锁并未释放
|
||||
<ul>
|
||||
`;
|
||||
let tmp = '';
|
||||
fatal.mutexes.forEach(m=>{
|
||||
tmp = '0x' + m.toString(16);
|
||||
fatalStr += `<li> ${tmp} </li>`;
|
||||
})
|
||||
fatalStr += `
|
||||
</ul>
|
||||
</li>
|
||||
`;
|
||||
})
|
||||
return fatalStr;
|
||||
}
|
||||
|
||||
// <li>
|
||||
// 线程 1005 已经拥有互斥量(0x2342fff), 继续申请互斥量(0x2342fffff)
|
||||
// </li>
|
||||
// <li>
|
||||
// 线程 1002 已经拥有互斥量(0x2342fff), 继续申请互斥量(0x2342fffff)
|
||||
// </li>
|
||||
// <li>
|
||||
// 线程 1001 已经拥有互斥量(0x2342fff), 继续申请互斥量(0x2342fffff)
|
||||
// </li>
|
||||
function parse_deadlockInfo(dlInfo:DeadlockInfo, dataList: object[], linksList: object[]) {
|
||||
let miStr = ``;
|
||||
if(dlInfo.cycle.length != dlInfo.threadid.length)
|
||||
{
|
||||
return miStr;
|
||||
}
|
||||
dlInfo.threadid.forEach((value, index)=>{
|
||||
if(dlInfo.cycle[index]){
|
||||
let tmp1 = '0x'+dlInfo.cycle[index].toString(16);
|
||||
let tmp2 = '0x'+dlInfo.cycle[(index+1)%dlInfo.cycle.length].toString(16);
|
||||
let val = `线程 ${value} 已经拥有互斥量(${tmp1}), 继续申请互斥量(${tmp2})`;
|
||||
miStr += `
|
||||
<li>
|
||||
${val}.
|
||||
</li>`;
|
||||
let pos = circledNodesPosition(300, 300, index, dlInfo.cycle.length);
|
||||
dataList.push({
|
||||
name: `互斥量 \n(${tmp1})`,
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
});
|
||||
linksList.push({
|
||||
source: index,
|
||||
target: (index+1)%dlInfo.cycle.length,
|
||||
value: `线程 ${value}`,
|
||||
lineStyle: {
|
||||
curveness: 0.2
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return miStr;
|
||||
}
|
||||
|
||||
export function prase_yaml2html(cmd: string, uri: string, webView: vscode.Webview, str: string) {
|
||||
let ymlObj = YAML.parse(str);
|
||||
const diskPath = vscode.Uri.file(join(uri, 'static', 'echarts.min.js'));
|
||||
const scriptUri = diskPath.with({ scheme: 'vscode-resource' }).toString();
|
||||
if(ymlObj.warn){
|
||||
if(ymlObj.normalInfo?.mutex){
|
||||
let sinfoList:SourceInfo[] = [];
|
||||
let dimensionsList:string[] = [];
|
||||
let seriesList: object[] = [];
|
||||
let miStr = parse_mutexInfo(ymlObj.normalInfo.mutex, sinfoList, dimensionsList, seriesList);
|
||||
return product_normalinfo_to_html(cmd, scriptUri, miStr, dimensionsList, sinfoList, seriesList);
|
||||
}
|
||||
}
|
||||
if(ymlObj.fatal){
|
||||
return product_fatalinfo_to_html(cmd, parse_fatalInfo(ymlObj.fatal));
|
||||
}
|
||||
if(ymlObj.deadlock){
|
||||
let dataList: object[] = [];
|
||||
let linksList: object[] = [];
|
||||
let dlStr = parse_deadlockInfo(ymlObj.deadlock, dataList, linksList);
|
||||
return product_deadlockinfo_to_html(cmd, scriptUri, dlStr, dataList, linksList);
|
||||
}
|
||||
return ``;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -2024,6 +2024,11 @@ yallist@^4.0.0:
|
|||
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.npmmirror.com/yaml/-/yaml-2.1.3.tgz#9b3a4c8aff9821b696275c79a8bee8399d945207"
|
||||
integrity sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==
|
||||
|
||||
yargs-parser@20.2.4:
|
||||
version "20.2.4"
|
||||
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
||||
|
|
|
@ -12,10 +12,12 @@
|
|||
"echart": "^0.1.3",
|
||||
"echarts": "^5.3.3",
|
||||
"element-ui": "^2.15.9",
|
||||
"vscode": "^1.1.37",
|
||||
"vue": "2.6.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/vscode-webview": "^1.57.0",
|
||||
"@vitejs/plugin-legacy": "^1.7.1",
|
||||
"@vue/runtime-dom": "^3.2.31",
|
||||
"typescript": "~4.7.3",
|
||||
|
@ -802,6 +804,14 @@
|
|||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.56",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-16.11.56.tgz",
|
||||
|
@ -814,6 +824,12 @@
|
|||
"integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/vscode-webview": {
|
||||
"version": "1.57.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/vscode-webview/-/vscode-webview-1.57.0.tgz",
|
||||
"integrity": "sha512-x3Cb/SMa1IwRHfSvKaZDZOTh4cNoG505c3NjTqGlMC082m++x/ETUmtYniDsw6SSmYzZXO8KBNhYxR0+VqymqA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vitejs/plugin-legacy": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-1.8.2.tgz",
|
||||
|
@ -1194,6 +1210,17 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
|
@ -1254,12 +1281,31 @@
|
|||
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.3",
|
||||
"resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.3.tgz",
|
||||
|
@ -1278,6 +1324,11 @@
|
|||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"node_modules/cache-content-type": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz",
|
||||
|
@ -1343,6 +1394,16 @@
|
|||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/consolidate": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmmirror.com/consolidate/-/consolidate-0.16.0.tgz",
|
||||
|
@ -1489,6 +1550,14 @@
|
|||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
|
@ -1628,6 +1697,19 @@
|
|||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
||||
},
|
||||
"node_modules/es6-promisify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||
"integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
|
||||
"dependencies": {
|
||||
"es6-promise": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.14.54",
|
||||
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz",
|
||||
|
@ -2002,7 +2084,6 @@
|
|||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
|
@ -2036,6 +2117,11 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
|
||||
|
@ -2065,6 +2151,22 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
|
||||
|
@ -2080,6 +2182,14 @@
|
|||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/growl": {
|
||||
"version": "1.10.5",
|
||||
"resolved": "https://registry.npmmirror.com/growl/-/growl-1.10.5.tgz",
|
||||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
||||
"engines": {
|
||||
"node": ">=4.x"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
|
||||
|
@ -2096,7 +2206,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
|
@ -2191,6 +2300,40 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
|
||||
"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
|
||||
"dependencies": {
|
||||
"@tootallnate/once": "1",
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
|
||||
|
@ -2428,6 +2571,118 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q=="
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==",
|
||||
"deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
|
||||
"dependencies": {
|
||||
"minimist": "0.0.8"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/mocha/-/mocha-5.2.0.tgz",
|
||||
"integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
|
||||
"dependencies": {
|
||||
"browser-stdout": "1.3.1",
|
||||
"commander": "2.15.1",
|
||||
"debug": "3.1.0",
|
||||
"diff": "3.5.0",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"glob": "7.1.2",
|
||||
"growl": "1.10.5",
|
||||
"he": "1.1.1",
|
||||
"minimatch": "3.0.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"supports-color": "5.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"_mocha": "bin/_mocha",
|
||||
"mocha": "bin/mocha"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/he": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/he/-/he-1.1.1.tgz",
|
||||
"integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==",
|
||||
"bin": {
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/mocha/node_modules/supports-color": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.4.0.tgz",
|
||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
|
||||
|
@ -2475,6 +2730,14 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/only": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz",
|
||||
|
@ -2488,6 +2751,14 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
|
||||
|
@ -2645,7 +2916,6 @@
|
|||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
@ -2659,6 +2929,15 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
|
@ -2973,6 +3252,96 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode": {
|
||||
"version": "1.1.37",
|
||||
"resolved": "https://registry.npmmirror.com/vscode/-/vscode-1.1.37.tgz",
|
||||
"integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==",
|
||||
"deprecated": "This package is deprecated in favor of @types/vscode and vscode-test. For more information please read: https://code.visualstudio.com/updates/v1_36#_splitting-vscode-package-into-typesvscode-and-vscodetest",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.2",
|
||||
"http-proxy-agent": "^4.0.1",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"mocha": "^5.2.0",
|
||||
"semver": "^5.4.1",
|
||||
"source-map-support": "^0.5.0",
|
||||
"vscode-test": "^0.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"vscode-install": "bin/install"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/vscode-test/-/vscode-test-0.4.3.tgz",
|
||||
"integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==",
|
||||
"deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name",
|
||||
"dependencies": {
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test/node_modules/agent-base": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-4.3.0.tgz",
|
||||
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
|
||||
"dependencies": {
|
||||
"es6-promisify": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test/node_modules/debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test/node_modules/http-proxy-agent": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
|
||||
"integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
|
||||
"dependencies": {
|
||||
"agent-base": "4",
|
||||
"debug": "3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test/node_modules/https-proxy-agent": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
|
||||
"integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
|
||||
"dependencies": {
|
||||
"agent-base": "^4.3.0",
|
||||
"debug": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-test/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/vscode/node_modules/semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "2.6.14",
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-2.6.14.tgz",
|
||||
|
@ -3041,6 +3410,11 @@
|
|||
"integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz",
|
||||
|
@ -3625,6 +3999,11 @@
|
|||
"picomatch": "^2.2.2"
|
||||
}
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.56",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-16.11.56.tgz",
|
||||
|
@ -3637,6 +4016,12 @@
|
|||
"integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/vscode-webview": {
|
||||
"version": "1.57.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/vscode-webview/-/vscode-webview-1.57.0.tgz",
|
||||
"integrity": "sha512-x3Cb/SMa1IwRHfSvKaZDZOTh4cNoG505c3NjTqGlMC082m++x/ETUmtYniDsw6SSmYzZXO8KBNhYxR0+VqymqA==",
|
||||
"dev": true
|
||||
},
|
||||
"@vitejs/plugin-legacy": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-1.8.2.tgz",
|
||||
|
@ -3974,6 +4359,14 @@
|
|||
"negotiator": "0.6.3"
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"requires": {
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
|
@ -4028,12 +4421,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.3",
|
||||
"resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.3.tgz",
|
||||
|
@ -4046,6 +4458,11 @@
|
|||
"update-browserslist-db": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"cache-content-type": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz",
|
||||
|
@ -4098,6 +4515,16 @@
|
|||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"consolidate": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmmirror.com/consolidate/-/consolidate-0.16.0.tgz",
|
||||
|
@ -4209,6 +4636,11 @@
|
|||
"resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
|
@ -4335,6 +4767,19 @@
|
|||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"dev": true
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
||||
},
|
||||
"es6-promisify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||
"integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
|
||||
"requires": {
|
||||
"es6-promise": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.14.54",
|
||||
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz",
|
||||
|
@ -4518,8 +4963,7 @@
|
|||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "2.0.2",
|
||||
|
@ -4544,6 +4988,11 @@
|
|||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
|
||||
|
@ -4563,6 +5012,19 @@
|
|||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
|
||||
|
@ -4575,6 +5037,11 @@
|
|||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.10.5",
|
||||
"resolved": "https://registry.npmmirror.com/growl/-/growl-1.10.5.tgz",
|
||||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
|
||||
|
@ -4587,8 +5054,7 @@
|
|||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.3",
|
||||
|
@ -4661,6 +5127,34 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"http-proxy-agent": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
|
||||
"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
|
||||
"requires": {
|
||||
"@tootallnate/once": "1",
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"requires": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
|
||||
|
@ -4856,6 +5350,94 @@
|
|||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/mocha/-/mocha-5.2.0.tgz",
|
||||
"integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
|
||||
"requires": {
|
||||
"browser-stdout": "1.3.1",
|
||||
"commander": "2.15.1",
|
||||
"debug": "3.1.0",
|
||||
"diff": "3.5.0",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"glob": "7.1.2",
|
||||
"growl": "1.10.5",
|
||||
"he": "1.1.1",
|
||||
"minimatch": "3.0.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"supports-color": "5.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"he": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/he/-/he-1.1.1.tgz",
|
||||
"integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.4.0.tgz",
|
||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
|
||||
|
@ -4891,6 +5473,14 @@
|
|||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"only": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz",
|
||||
|
@ -4901,6 +5491,11 @@
|
|||
"resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
|
||||
|
@ -5023,8 +5618,7 @@
|
|||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.2",
|
||||
|
@ -5032,6 +5626,15 @@
|
|||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
|
@ -5246,6 +5849,77 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"vscode": {
|
||||
"version": "1.1.37",
|
||||
"resolved": "https://registry.npmmirror.com/vscode/-/vscode-1.1.37.tgz",
|
||||
"integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==",
|
||||
"requires": {
|
||||
"glob": "^7.1.2",
|
||||
"http-proxy-agent": "^4.0.1",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"mocha": "^5.2.0",
|
||||
"semver": "^5.4.1",
|
||||
"source-map-support": "^0.5.0",
|
||||
"vscode-test": "^0.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-test": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/vscode-test/-/vscode-test-0.4.3.tgz",
|
||||
"integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==",
|
||||
"requires": {
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-4.3.0.tgz",
|
||||
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
|
||||
"requires": {
|
||||
"es6-promisify": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"http-proxy-agent": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
|
||||
"integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
|
||||
"requires": {
|
||||
"agent-base": "4",
|
||||
"debug": "3.1.0"
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
|
||||
"integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
|
||||
"requires": {
|
||||
"agent-base": "^4.3.0",
|
||||
"debug": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue": {
|
||||
"version": "2.6.14",
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-2.6.14.tgz",
|
||||
|
@ -5302,6 +5976,11 @@
|
|||
"integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz",
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"echart": "^0.1.3",
|
||||
"echarts": "^5.3.3",
|
||||
"element-ui": "^2.15.9",
|
||||
"vscode": "^1.1.37",
|
||||
"vue": "2.6.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -24,6 +25,7 @@
|
|||
"vite-plugin-vue2": "^1.9.3",
|
||||
"vue-template-babel-compiler": "^1.2.0",
|
||||
"vue-template-compiler": "2.6.14",
|
||||
"vue-tsc": "^0.37.3"
|
||||
"vue-tsc": "^0.37.3",
|
||||
"@types/vscode-webview": "^1.57.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<template>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick" style="width: 80%;margin: auto;">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick" type="border-card" style="width: 80%;margin: auto;">
|
||||
<el-tab-pane label="本地检测" name="first">
|
||||
<div style="width: 60%;margin:auto">
|
||||
<br />
|
||||
<el-radio v-model="radio" label="1">检测指定进程</el-radio>
|
||||
<el-radio v-model="radio" label="2">检测可执行程序</el-radio>
|
||||
<div id="pid" v-if="radio == '1'">
|
||||
<div id="pid">
|
||||
<br />
|
||||
<el-input v-model="local_pid_input" placeholder="请输入被检测进程PID"></el-input>
|
||||
</div>
|
||||
|
||||
<div id="comm" v-if="radio == '2'">
|
||||
<br />
|
||||
<el-input v-model="local_cmd_input" placeholder="请输入被检测程序命令行"></el-input>
|
||||
<br /><br />
|
||||
<el-input v-model="local_env_input" placeholder="请输入被检测程序环境变量"></el-input>
|
||||
</div>
|
||||
<br />
|
||||
<el-input placeholder="请输入管理员密码" v-model="local_passwd_input" show-password></el-input>
|
||||
<el-input placeholder="请输入用户密码" v-model="local_passwd_input" show-password></el-input>
|
||||
<br /> <br />
|
||||
<el-button type="primary" v-on:click="begin_local_check(1,radio)">开始检测</el-button>
|
||||
<el-button type="primary" v-on:click="begin_local_check()">开始检测</el-button>
|
||||
</div>
|
||||
<br />
|
||||
<el-card v-loading="loading" element-loading-text="正在检测..." class="box-card" style="width: 80%;margin: auto;">
|
||||
<div slot="header" class="clearfix" v-if="loading == false">
|
||||
<span>{{ local_thread_data }}</span>
|
||||
</div>
|
||||
<div v-if="loading == false && pid == false" v-for="o in 4" :key="o" class="text item">
|
||||
{{'线程信息: ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card id="main_local" style="width: 80%; height: 400px; margin: auto;"></el-card >
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="远程检测" name="second">
|
||||
|
@ -36,20 +37,17 @@
|
|||
<br /> <br />
|
||||
<el-button type="primary" @click="begin_remote_check()">开始检测</el-button>
|
||||
</div>
|
||||
<br />
|
||||
<el-card class="box-card" style="width: 80%;margin: auto;">
|
||||
<div>
|
||||
<span>线程死锁关系:</span>
|
||||
<br>
|
||||
<span>{{ remote_thread_data }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card id="main_remote" style="width: 80%; height: 400px; margin: auto;"></el-card>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-card v-loading="loading" element-loading-text="正在检测..." class="box-card" style="width: 80%;margin: auto;">
|
||||
<div slot="header" class="clearfix" v-if="loading == false">
|
||||
<span>检测结果</span>
|
||||
</div>
|
||||
<div v-if="loading== false" v-for="o in 4" :key="o" class="text item">
|
||||
{{'线程信息: ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card id="main" style="width: 80%; height: 400px; margin: auto;">
|
||||
</el-card >
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -101,137 +99,429 @@ function TableData () {
|
|||
export default {
|
||||
data() {
|
||||
return {
|
||||
local_pid_input: -1,
|
||||
local_pid_input: '',
|
||||
local_passwd_input: '',
|
||||
local_cmd_input: '',
|
||||
local_env_input: '',
|
||||
remote_account_input: '',
|
||||
remote_passwd_input: '',
|
||||
remote_addr_input: '',
|
||||
remote_pid_input: -1,
|
||||
radio: '1',
|
||||
remote_pid_input: '',
|
||||
loading: true,
|
||||
pid: false,
|
||||
afterchecked: false,
|
||||
deadlockgraph: {},
|
||||
deadlockinfo: [],
|
||||
lockinfo:[]
|
||||
lockinfo:[],
|
||||
activeName: "first",
|
||||
local_thread_data: '',
|
||||
remote_thread_data: '',
|
||||
thread_info: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.chartDraw();
|
||||
this.listener();
|
||||
this.messageListen();
|
||||
},
|
||||
methods:{
|
||||
begin_local_check(isLocal, isPid){
|
||||
let td = new TableData();
|
||||
if(isLocal){
|
||||
|
||||
}else if(!isLocal){
|
||||
td.CmdType = cmd_type.REMOTE_PID;
|
||||
td.Pid = remote_pid_input;
|
||||
td.Addr = remote_addr_input;
|
||||
td.User = remote_
|
||||
}
|
||||
this.$vscode.postMessage(data);
|
||||
messageListen() {
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.data.res.CmdType == 1) {
|
||||
if(event.data.res.success=='success') {
|
||||
this.drawDeadGraph(event.data.res.data);
|
||||
}
|
||||
// else if (event.data.res.success=='error') {
|
||||
// this.$message({
|
||||
// showClose: true,
|
||||
// message:"local-deadlock-detect command exec failed!",
|
||||
// type: event.data.res.success=='success'?'success':'error'
|
||||
// });
|
||||
// }
|
||||
// else {
|
||||
// this.$message({
|
||||
// showClose: true,
|
||||
// message: event.data.res.msg,
|
||||
// type: event.data.res.success=='success'?'success':'error'
|
||||
// });
|
||||
// }
|
||||
}
|
||||
else if (event.data.res.CmdType == 3) {
|
||||
if(event.data.res.success=='success'){
|
||||
this.drawDeadGraph(event.data.res.data);
|
||||
}
|
||||
// else if (event.data.res.success=='error') {
|
||||
// this.$message({
|
||||
// showClose: true,
|
||||
// message:"local-deadlock-detect command exec failed!",
|
||||
// type: event.data.res.success=='success'?'success':'error'
|
||||
// });
|
||||
// }
|
||||
// else {
|
||||
// this.$message({
|
||||
// showClose: true,
|
||||
// message: event.data.res.msg,
|
||||
// type: event.data.res.success=='success'?'success':'error'
|
||||
// });
|
||||
// }
|
||||
}
|
||||
})
|
||||
},
|
||||
chartDraw() {
|
||||
var myChart = echarts.init(document.getElementById('main'));
|
||||
var option;
|
||||
option = {
|
||||
title: {
|
||||
text: '死锁关系图'
|
||||
},
|
||||
tooltip: {},
|
||||
animationDurationUpdate: 1500,
|
||||
animationEasingUpdate: 'quinticInOut',
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
layout: 'none',
|
||||
symbolSize: 50,
|
||||
roam: false,
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
edgeSymbol: ['circle', 'arrow'],
|
||||
edgeSymbolSize: [4, 10],
|
||||
edgeLabel: {
|
||||
fontSize: 20
|
||||
},
|
||||
data: [
|
||||
{
|
||||
name: 'Node 1',
|
||||
x: 300,
|
||||
y: 300
|
||||
},
|
||||
{
|
||||
name: 'Node 2',
|
||||
x: 800,
|
||||
y: 300
|
||||
},
|
||||
{
|
||||
name: 'Node 3',
|
||||
x: 550,
|
||||
y: 100
|
||||
},
|
||||
{
|
||||
name: 'Node 4',
|
||||
x: 550,
|
||||
y: 500
|
||||
}
|
||||
],
|
||||
// links: [],
|
||||
links: [
|
||||
{
|
||||
source: 0,
|
||||
target: 1,
|
||||
symbolSize: [5, 20],
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
lineStyle: {
|
||||
width: 5,
|
||||
curveness: 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
source: 'Node 2',
|
||||
target: 'Node 1',
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
lineStyle: {
|
||||
curveness: 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
source: 'Node 1',
|
||||
target: 'Node 3'
|
||||
},
|
||||
{
|
||||
source: 'Node 2',
|
||||
target: 'Node 3'
|
||||
},
|
||||
{
|
||||
source: 'Node 2',
|
||||
target: 'Node 4'
|
||||
},
|
||||
{
|
||||
source: 'Node 1',
|
||||
target: 'Node 4'
|
||||
}
|
||||
],
|
||||
lineStyle: {
|
||||
opacity: 0.9,
|
||||
width: 2,
|
||||
curveness: 0
|
||||
|
||||
begin_local_check(){
|
||||
let td = new TableData();
|
||||
let local_form = {};
|
||||
|
||||
let re = this.local_info_verify(this.local_pid_input, this.local_passwd_input);
|
||||
if(re == '-1')
|
||||
return;
|
||||
local_form.pid = this.local_pid_input;
|
||||
local_form.pwd = this.local_passwd_input;
|
||||
local_form.CmdType = cmd_type.LOCAL_PID;
|
||||
this.$vscode.postMessage({form: local_form});
|
||||
},
|
||||
|
||||
begin_remote_check(){
|
||||
let remote_form = {};
|
||||
let re = this.remote_info_verify(this.remote_pid_input, this.remote_passwd_input, this.remote_account_input, this.remote_addr_input);
|
||||
if(re == '-1')
|
||||
return;
|
||||
remote_form.pid = this.remote_pid_input;
|
||||
remote_form.pwd = this.remote_passwd_input;
|
||||
remote_form.CmdType = cmd_type.REMOTE_PID;
|
||||
remote_form.user = this.remote_account_input;
|
||||
remote_form.ip = this.remote_addr_input;
|
||||
this.$vscode.postMessage({form: remote_form});
|
||||
},
|
||||
|
||||
local_info_verify(pid, pwd) {
|
||||
if(!pid){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入pid',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
if(!pwd){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入用户密码',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
return '0';
|
||||
},
|
||||
|
||||
remote_info_verify(pid, pwd, user, ip) {
|
||||
if(!pid){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入pid',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
if(!pwd){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入用户密码',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
if(!user){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入远程用户账号!',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
if(!ip){
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'请输入远程IP地址!',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
return '0';
|
||||
},
|
||||
|
||||
lockInfoInit(data){
|
||||
if (this.activeName == "first")
|
||||
this.local_thread_data = '';
|
||||
if (this.activeName == "second")
|
||||
this.remote_thread_data = '';
|
||||
this.thread_info = [];
|
||||
|
||||
let sub=data.split(/\n/);
|
||||
console.log(sub);
|
||||
this.pid = true;
|
||||
this.loading = false;
|
||||
sub.forEach(item=>{
|
||||
if(/LWP/g.test(item)){
|
||||
let obj={};
|
||||
obj.threadID=item.split(/LWP /)[1].split(/\)/)[0];
|
||||
obj.lockID=item.split(/\{/)[1].split(/\}/)[0];
|
||||
obj.ownID=item.split(/LWP /)[2].split(/\)/)[0];
|
||||
this.thread_info.push(obj);
|
||||
if (this.activeName == "first") {
|
||||
this.local_thread_data = `${this.local_thread_data}线程${obj.threadID}等待锁${obj.lockID},锁${obj.lockID}被线程${obj.ownID}拥有;\n`;
|
||||
console.log(this.local_thread_data);
|
||||
} else {
|
||||
this.remote_thread_data = `${this.remote_thread_data}线程${obj.threadID}等待锁${obj.lockID},锁${obj.lockID}被线程${obj.ownID}拥有;`;
|
||||
console.log(this.remote_thread_data);
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
option && myChart.setOption(option);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
drawDeadGraph(data){
|
||||
if(/没有发现死锁/g.test(data)){
|
||||
let myChart = echarts.init(document.getElementById(this.activeName == "first" ? "main_local" : "main_remote"));
|
||||
myChart.setOption({}, true);
|
||||
myChart.clear();
|
||||
if (this.activeName == "first") {
|
||||
this.local_thread_data = '';
|
||||
} else {
|
||||
this.remote_thread_data = '';
|
||||
}
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message:'没有发现死锁!',
|
||||
type:'warning',
|
||||
});
|
||||
return '-1';
|
||||
}
|
||||
this.lockInfoInit(data);
|
||||
let echartsData=this.getdeadgraphData(this.thread_info);
|
||||
this.deadgraph(echartsData);
|
||||
},
|
||||
|
||||
getdeadgraphData(lockInfo){
|
||||
let data=[];
|
||||
let createdNodeArr=[];
|
||||
let threadPos={};
|
||||
let lockPos={};
|
||||
let thPosX=0;
|
||||
let thPosY=0
|
||||
let linkDataArr=[];
|
||||
lockInfo.forEach((item,index)=>{
|
||||
|
||||
thPosX+=50;
|
||||
let obj={
|
||||
name: item.threadID,
|
||||
// x: threadPos[item.threadID],
|
||||
x: thPosX,
|
||||
y: thPosY,
|
||||
symbol:'rect',
|
||||
};
|
||||
data.push(obj);
|
||||
createdNodeArr.push(item.threadID);
|
||||
|
||||
if(index==lockInfo.length-1){
|
||||
thPosY=0;
|
||||
}else{
|
||||
thPosY+=50;
|
||||
}
|
||||
if(!lockPos[item.ownID]){
|
||||
lockPos[item.ownID]=thPosY;
|
||||
}else{
|
||||
lockPos[item.ownID]+=50;
|
||||
lockPos[item.ownID]+=thPosY;
|
||||
|
||||
}
|
||||
|
||||
obj={
|
||||
name: '锁'+item.lockID,
|
||||
// x: threadPos[item.threadID],
|
||||
x:thPosX,
|
||||
// y: lockPos[item.ownID],
|
||||
y:thPosY,
|
||||
symbol:'circle',
|
||||
};
|
||||
data.push(obj);
|
||||
createdNodeArr.push('锁'+item.lockID);
|
||||
|
||||
let linkObj={
|
||||
source: item.threadID,
|
||||
target: '锁'+item.lockID,
|
||||
label: {
|
||||
show: true,
|
||||
formatter:'等待'
|
||||
},
|
||||
lineStyle: {
|
||||
curveness: 0.2
|
||||
}
|
||||
}
|
||||
let linkObj1={
|
||||
source: item.ownID,
|
||||
target: '锁'+item.lockID,
|
||||
label: {
|
||||
show: true,
|
||||
formatter:'拥有'
|
||||
},
|
||||
lineStyle: {
|
||||
curveness: 0.2
|
||||
}
|
||||
}
|
||||
linkDataArr.push(linkObj,linkObj1);
|
||||
})
|
||||
let returnData={
|
||||
data:data,
|
||||
linkDataArr:linkDataArr
|
||||
};
|
||||
return returnData;
|
||||
}
|
||||
,
|
||||
deadgraph(echartsData) {
|
||||
// var myChart = echarts.init(document.getElementById(this.activeName == "first" ? "main_local" : "main_remote"));
|
||||
// var myChart = echarts.init(document.getElementById("main_local"));
|
||||
// myChart.setOption({}, true);
|
||||
// myChart = echarts.init(document.getElementById("main_remote"));
|
||||
// myChart.setOption({}, true);
|
||||
let myChart = echarts.init(document.getElementById(this.activeName == "first" ? "main_local" : "main_remote"));
|
||||
// var op = myChart.getOption();
|
||||
// console.log(op);
|
||||
let option = {
|
||||
title: {
|
||||
text: '死锁关系图'
|
||||
},
|
||||
tooltip: {},
|
||||
animationDurationUpdate: 1500,
|
||||
animationEasingUpdate: 'quinticInOut',
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
layout: 'none',
|
||||
symbolSize: 50,
|
||||
roam: true,
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
edgeSymbol: ['circle', 'arrow'],
|
||||
edgeSymbolSize: [4, 10],
|
||||
itemStyle: {
|
||||
color: '#bbb',
|
||||
show: true
|
||||
},
|
||||
edgeLabel: {
|
||||
fontSize: 20
|
||||
},
|
||||
data: echartsData.data,
|
||||
|
||||
links: echartsData.linkDataArr,
|
||||
|
||||
lineStyle: {
|
||||
opacity: 0.9,
|
||||
width: 1,
|
||||
curveness: 0.2
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
console.log("打印option数据");
|
||||
myChart.setOption(option, true);
|
||||
},
|
||||
// chartDraw() {
|
||||
// var myChart = echarts.init(document.getElementById('main'));
|
||||
// var option;
|
||||
// option = {
|
||||
// title: {
|
||||
// text: '死锁关系图'
|
||||
// },
|
||||
// tooltip: {},
|
||||
// animationDurationUpdate: 1500,
|
||||
// animationEasingUpdate: 'quinticInOut',
|
||||
// series: [
|
||||
// {
|
||||
// type: 'graph',
|
||||
// layout: 'none',
|
||||
// symbolSize: 50,
|
||||
// roam: false,
|
||||
// label: {
|
||||
// show: true
|
||||
// },
|
||||
// edgeSymbol: ['circle', 'arrow'],
|
||||
// edgeSymbolSize: [4, 10],
|
||||
// edgeLabel: {
|
||||
// fontSize: 20
|
||||
// },
|
||||
// data: [
|
||||
// {
|
||||
// name: 'Node 1',
|
||||
// x: 300,
|
||||
// y: 300
|
||||
// },
|
||||
// {
|
||||
// name: 'Node 2',
|
||||
// x: 800,
|
||||
// y: 300
|
||||
// },
|
||||
// {
|
||||
// name: 'Node 3',
|
||||
// x: 550,
|
||||
// y: 100
|
||||
// },
|
||||
// {
|
||||
// name: 'Node 4',
|
||||
// x: 550,
|
||||
// y: 500
|
||||
// }
|
||||
// ],
|
||||
// // links: [],
|
||||
// links: [
|
||||
// {
|
||||
// source: 0,
|
||||
// target: 1,
|
||||
// symbolSize: [5, 20],
|
||||
// label: {
|
||||
// show: true
|
||||
// },
|
||||
// lineStyle: {
|
||||
// width: 5,
|
||||
// curveness: 0.2
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// source: 'Node 2',
|
||||
// target: 'Node 1',
|
||||
// label: {
|
||||
// show: true
|
||||
// },
|
||||
// lineStyle: {
|
||||
// curveness: 0.2
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// source: 'Node 1',
|
||||
// target: 'Node 3'
|
||||
// },
|
||||
// {
|
||||
// source: 'Node 2',
|
||||
// target: 'Node 3'
|
||||
// },
|
||||
// {
|
||||
// source: 'Node 2',
|
||||
// target: 'Node 4'
|
||||
// },
|
||||
// {
|
||||
// source: 'Node 1',
|
||||
// target: 'Node 4'
|
||||
// }
|
||||
// ],
|
||||
// lineStyle: {
|
||||
// opacity: 0.9,
|
||||
// width: 2,
|
||||
// curveness: 0
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
// option && myChart.setOption(option);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -4,9 +4,11 @@ import 'element-ui/lib/theme-chalk/index.css';
|
|||
|
||||
import App from './App.vue';
|
||||
|
||||
|
||||
Vue.use(ElementUI);
|
||||
|
||||
const vscode = acquireVsCodeApi()
|
||||
Vue.prototype.$vscode = vscode
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
render: h => h(App)
|
||||
|
|
Loading…
Reference in New Issue