13 Commits
dev ... v0.13.0

Author SHA1 Message Date
Henning Dieterichs
fdc0b00f6b v0.13.0 2020-03-02 11:04:35 +01:00
Henning Dieterichs
f12ea19369 Implements the debugVisualizer.debugAdapterConfigurations configuration option. 2020-03-02 11:02:18 +01:00
Henning Dieterichs
f6a554c897 Improves implementation documentation. 2020-02-29 21:58:18 +01:00
Henning Dieterichs
5318b5e4ae Moved "extension/ui" to "webview", removed "shared". 2020-02-29 21:31:22 +01:00
Henning Dieterichs
f55bef23c2 Adds build instructions. 2020-02-25 12:28:18 +01:00
Henning Dieterichs
78a133505c v0.12.1 2020-02-24 23:02:15 +01:00
Henning Dieterichs
1226a43f89 Updates C# demo to updated evaluation result handling. 2020-02-24 23:01:37 +01:00
Henning Dieterichs
2bc1ce380d Tries to parse evaluated string as json string if it could not be parsed otherwise. Should make the debug visualizer compatible with C++. 2020-02-24 22:53:46 +01:00
Henning Dieterichs
43e0a13dca Updates dependencies and fixes problem with plotly types. 2020-02-24 09:48:38 +01:00
Henning Dieterichs
89b96d53b7 Merge pull request #21 from Almenon/patch-1
Add graph demo for python
2020-02-24 09:13:05 +01:00
Almenon
9a5d6a083c Add graph demo for python 2020-02-23 21:19:16 -08:00
Henning Dieterichs
994c9f6248 v0.12.0 2020-02-23 13:35:59 +01:00
Henning Dieterichs
d4202d88e2 Removes unused "source" selection. 2020-02-23 13:24:57 +01:00
73 changed files with 722 additions and 303 deletions

View File

@@ -2,7 +2,58 @@
[![](https://img.shields.io/twitter/follow/hediet_dev.svg?style=social)](https://twitter.com/intent/follow?screen_name=hediet_dev)
See the [extension](extension) directory for the extension readme.
See [here](./extension/README.md) for the readme of the extension.
You can get the extension in the [marketplace](https://marketplace.visualstudio.com/items?itemName=hediet.debug-visualizer).
![](./docs/doubly-linked-list-reverse-demo.gif)
This readme extends the [readme](./extension/README.md) of the extension with implementation details.
## Build Instructions
- Clone the repository
- Run `yarn` in the repository root
- Run `yarn build`
## Dev Instructions
This project uses yarn workspaces and consists of the sub-projects _data-extraction_, _extension_ and _webview_.
To setup a dev environment, follow these steps:
- Clone the repository
- Run `yarn` in the repository root
- Run `yarn build` initially (or `yarn dev` for every sub-project)
- Run `yarn dev` for the sub-project (i.e. in its folder) you are working on.
For the _webview_ project, `yarn dev` will serve the react application on port 8080.
Certain query parameters need to be so that the UI can connect to the debug visualizer extension.
You can use VS Code to launch and debug the extension.
Chose the preconfigured `Run Extension (Dev UI)` as debug configuration
so that the extension loads the UI from the webpack server.
Otherwise, the extension will start a webserver on its own, hosting the `dist` folder of the _webview_ project.
## Publish Instructions
- Follow the Build Instructions
- `cd extension`
- `yarn pub`
## Architecture
![](./docs/exported/main/Main.png)
### webview
Provides the UI and is hosted inside a webview in VS Code.
### extension
Creates the webview in VS Code, hosts a webserver and a websocket server.
The webserver serves the _webview_ project that is loaded by the webview.
After the webview is loaded, it connects to the websocket server.
The websocket server is used to evaluate expressions and is secured by a random token.
### data-extraction
Provides types and a JS runtime for data extraction.

View File

@@ -1,7 +1,7 @@
{
"name": "@hediet/debug-visualizer-data-extraction",
"description": "A library that helps implementing data extractors for the Debug Visualizer VS Code extension.",
"version": "0.11.0",
"version": "0.12.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {
@@ -27,9 +27,9 @@
},
"dependencies": {},
"devDependencies": {
"typescript": "^3.7.5",
"@types/plotly.js": "^1.44.28",
"@types/node": "^13.7.1",
"typescript": "^3.8.2",
"@types/plotly.js": "1.44.28",
"@types/node": "^13.7.4",
"tslint": "^6.0.0",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",

View File

@@ -1,4 +1,10 @@
{
"debugVisualizer.useChromeKioskMode": false,
"editor.minimap.enabled": false
"editor.minimap.enabled": false,
"debugVisualizer.debugAdapterConfigurations": {
"php": {
"context": "watch",
"expressionTemplate": "${expr}"
}
}
}

View File

@@ -52,7 +52,7 @@ namespace Demo
}
}
public ExtractedData Visualize()
public string Visualize()
{
var list = new Node(default(T)!) { Next = this.Head };
return GraphData.From(new[] { list }, (item, info) =>
@@ -65,7 +65,7 @@ namespace Demo
if (item.Next != null)
info.AddEdge(item.Next!, label: item == list ? "head" : "next");
return info;
});
}).ToString();
}
}
}

View File

@@ -3,11 +3,9 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@hediet/live-debug": "^0.5.2",
"@hediet/node-reload": "0.7.0",
"@hediet/std": "^0.4.0",
"@types/node": "^13.7.1",
"typescript": "^3.5.3"
"@hediet/node-reload": "0.7.3",
"@types/node": "^13.7.4",
"typescript": "^3.8.2"
},
"scripts": {
"dev": "tsc --watch"

36
demo/python/graph.py Normal file
View File

@@ -0,0 +1,36 @@
# Install the python extension for VS Code
# (https:#marketplace.visualstudio.com/items?itemName=ms-python.python).
# The Debug Visualizer has no support for Python data extractors yet,
# so to visualize data, your value must be a valid JSON string representing the data.
# See readme for supported data schemas.
from json import dumps
from random import randint
graph = {
"kind": {"graph": True},
"nodes": [
{"id": "1", "label": "1"}
],
"edges": []
}
for i in range(2,100):
# add a node
id = str(i)
graph["nodes"].append({"id": id, "label": id})
# connects the node to a random edge
targetId = str(randint(1, i - 1))
graph["edges"].append({"from": id, "to": targetId})
json_graph = dumps(graph)
print("i is " + str(i))
# try setting a breakpoint right above
# then put json_graph into the visualization console and press enter
# when you step through the code each time you hit the breakpoint
# the graph should automatically refresh!
# example of json_graph visualization with 10 nodes:
# https://i.imgur.com/RqZuYHH.png
print("finished")

BIN
docs/exported/main/Main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

14
docs/main.plantuml Normal file
View File

@@ -0,0 +1,14 @@
@startuml Main
[data-extraction]
[webview]
[extension]
[webview] ..> [extension]: "Uses RPC contracts, connects using websockets"
[extension] ..> [webview]: "Loads into a Webview in VS Code"
[extension] ..> [data-extraction]: "Injects Runtime into JavaScript applications"
[webview] ..> [data-extraction]: "Uses common types"
@enduml

View File

@@ -1,13 +1,24 @@
# Change Log
## 0.9.0
## 0.13.0
- Initial release
- Adds "debugVisualizer.debugAdapterConfigurations" config to customize the expression template.
- Code Restructuring
## 0.10.0
## 0.12.1
- Minor refactoring of `@hediet/debug-visualizer-data-extraction`'s API
- Improved documentation.
- Tries to parse evaluated strings twice as JSON in case of C++/C# escape sequences.
## 0.12.0
- Generic Debug Adapter Support (tested with PHP, Java, C#)
- Dark Theme Support
- Grid Visualizer
- Some Bugfixes
## 0.11.1
- Fixes crash on start
## 0.11.0
@@ -18,6 +29,11 @@
- Plotly Data Extractor
- Some Bugfixes
## 0.11.1
## 0.10.0
- Fixes crash on start
- Minor refactoring of `@hediet/debug-visualizer-data-extraction`'s API
- Improved documentation.
## 0.9.0
- Initial release

View File

@@ -239,6 +239,30 @@ Creates Grid visualization data for an array.
![](../docs/multiline-expression.png)
## Configuration
This extension provides these configuration options:
- `debugVisualizer.debugAdapterConfigurations`
Allows to set expression templates for specific debug adapter types.
Example:
```json
"debugVisualizer.debugAdapterConfigurations": {
"lldb": {
"expressionTemplate": "script to_json(\"${expr}\")",
"context": "repl"
}
}
```
Configurations here overwrite the built-in support for the corresponding debug adapter type.
* `debugVisualizer.useChromeKioskMode`
Specifies whether to pop out Debug Visualization Views with Chrome in Kiosk Mode. Uses the default browser otherwise or if Chrome is not found. Defaults to `true`.
# See Also
This extension works very well together with my library [`@hediet/node-reload`](https://github.com/hediet/node-reload) for TypeScript/JavaScript.

View File

@@ -1,9 +1,10 @@
{
"name": "debug-visualizer",
"private": true,
"displayName": "Debug Visualizer",
"description": "An extension that visualizes values while debugging.",
"icon": "docs/logo.png",
"version": "0.11.1",
"version": "0.13.0",
"license": "MIT",
"engines": {
"vscode": "^1.35.0"
@@ -41,26 +42,47 @@
"type": "boolean",
"default": true,
"description": "Pop out Debug Visualization Views with Chrome in Kiosk Mode."
},
"debugVisualizer.debugAdapterConfigurations": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"expressionTemplate": {
"type:": "string",
"description": "A template for the final expression sent to the debugger for evaluation. Use `${expr}` to refer to the currently visualized expression."
},
"context": {
"type": "string",
"enum": [
"watch",
"repl"
],
"description": "The context to use for evaluating the expression."
}
}
}
}
}
}
},
"scripts": {
"pub": "vsce publish --yarn --baseImagesUrl https://github.com/hediet/vscode-debug-visualizer/raw/master/extension --baseContentUrl https://github.com/hediet/vscode-debug-visualizer/raw/master/extension",
"package": "vsce package --yarn",
"vscode:prepublish": "yarn build",
"build": "webpack --mode production",
"dev": "tsc -watch -p ./"
"dev": "shx rm -rf dist && tsc -watch -p ./"
},
"dependencies": {
"@hediet/std": "^0.6.0",
"@hediet/typed-json-rpc": "^0.7.7",
"@hediet/typed-json-rpc-websocket-server": "^0.7.7",
"chrome-launcher": "^0.11.2",
"@hediet/node-reload": "^0.7.2",
"chrome-launcher": "^0.12.0",
"@hediet/node-reload": "^0.7.3",
"express": "^4.17.1",
"open": "^6.4.0",
"open": "^7.0.2",
"serve-static": "^1.14.1",
"ws": "^7.1.1",
"ws": "^7.2.1",
"crypto-random-string": "^3.1.0"
},
"devDependencies": {
@@ -68,12 +90,13 @@
"@types/copy-webpack-plugin": "^5.0.0",
"@types/express": "^4.17.2",
"@types/serve-static": "^1.13.3",
"@types/node": "^13.7.1",
"@types/vscode": "^1.35.0",
"@types/node": "^13.7.4",
"@types/vscode": "1.35.0",
"tslint": "^6.0.0",
"typescript": "^3.7.5",
"typescript": "^3.8.2",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"ts-loader": "^6.2.1"
"ts-loader": "^6.2.1",
"shx": "^0.3.2"
}
}

View File

@@ -1,28 +1,99 @@
import { workspace } from "vscode";
import { Disposable } from "@hediet/std/disposable";
import { EventEmitter, EventSource } from "@hediet/std/events";
import { observable } from "mobx";
import { DataExtractorId } from "@hediet/debug-visualizer-data-extraction";
export const useChromeKioskModeKey = "debugVisualizer.useChromeKioskMode";
const useChromeKioskModeKey = "debugVisualizer.useChromeKioskMode";
const debugAdapterConfigsKey = "debugVisualizer.debugAdapterConfigurations";
export class Config {
private changeEventEmitter = new EventEmitter();
public readonly onChange: EventSource = this.changeEventEmitter;
public dispose = Disposable.fn();
@observable
private _useChromeKioskMode!: boolean;
@observable
private _debugAdapterConfigs!: DebugAdapterConfigs;
public get useChromeKioskMode(): boolean {
return this._useChromeKioskMode;
}
public get debugAdapterConfigs(): DebugAdapterConfigs {
return this._debugAdapterConfigs;
}
constructor() {
this.updateConfig();
this.dispose.track(
workspace.onDidChangeConfiguration(() => {
this.changeEventEmitter.emit();
this.updateConfig();
})
);
}
public useChromeKioskMode(): boolean {
private updateConfig(): void {
const c = workspace.getConfiguration();
const b = c.get<boolean>(useChromeKioskModeKey);
if (b === undefined) {
return true;
this._useChromeKioskMode = mapUndefined(
c.get<boolean>(useChromeKioskModeKey),
true
);
this._debugAdapterConfigs = mapUndefined(
c.get<DebugAdapterConfigs>(debugAdapterConfigsKey),
{}
);
}
public getDebugAdapterConfig(
debugAdapterType: string
): DebugAdapterConfig | undefined {
const c = this.debugAdapterConfigs[debugAdapterType];
if (!c) {
return undefined;
}
return b;
return {
context: c.context || "watch",
getFinalExpression: ({ expression, preferredExtractorId }) =>
evaluateTemplate(c.expressionTemplate || "${expr}", {
expr: expression,
preferredDataExtractorId: preferredExtractorId || "",
}),
};
}
}
function mapUndefined<T>(val: T | undefined, defaultVal: T) {
if (val === undefined) {
return defaultVal;
}
return val;
}
type DebugAdapterConfigs = {
[debugAdapter: string]: {
context?: "watch" | "repl";
expressionTemplate?: "string";
};
};
export interface DebugAdapterConfig {
context: "watch" | "repl";
getFinalExpression(vars: {
expression: string;
preferredExtractorId: DataExtractorId | undefined;
}): string;
}
function evaluateTemplate(
template: string,
data: Record<string, string>
): string {
let result = template;
for (const [key, val] of Object.entries(data)) {
result = result.split(`\${${key}}`).join(val);
}
return result;
}

View File

@@ -1,5 +1,5 @@
import { Disposable } from "@hediet/std/disposable";
import { debugVisualizerUIContract } from "@hediet/debug-visualizer-vscode-shared";
import { debugVisualizerUIContract } from "./contract";
import { ConsoleRpcLogger, RequestHandlingError } from "@hediet/typed-json-rpc";
import { EvaluationWatcher, DataSource } from "./DataSource/DataSource";
import { WebSocketStream } from "@hediet/typed-json-rpc-websocket";
@@ -76,7 +76,7 @@ export class ConnectionHandler {
});
let opened = false;
if (config.useChromeKioskMode()) {
if (config.useChromeKioskMode) {
opened = await launchChrome(url);
}
if (!opened) {

View File

@@ -0,0 +1,49 @@
import { DataExtractorId } from "@hediet/debug-visualizer-data-extraction";
import { VsCodeDebugSession } from "../../VsCodeDebugger";
import {
DataExtractionProviderFactory,
DataExtractionProvider,
} from "./DataExtractionProvider";
import { Config, DebugAdapterConfig } from "../../Config";
import { GenericDataExtractionProvider } from "./GenericDataExtractionProviderFactory";
export class ConfiguredDataExtractionProviderFactory
implements DataExtractionProviderFactory {
constructor(private readonly config: Config) {}
createDataExtractionProvider(
session: VsCodeDebugSession
): DataExtractionProvider | undefined {
const config = this.config.getDebugAdapterConfig(session.session.type);
if (!config) {
return undefined;
}
return new ConfiguredDataExtractionProvider(session, config);
}
}
class ConfiguredDataExtractionProvider extends GenericDataExtractionProvider {
constructor(
session: VsCodeDebugSession,
private readonly config: DebugAdapterConfig
) {
super(session);
}
protected getContext() {
return this.config.context;
}
protected getFinalExpression({
expression,
preferredExtractorId,
}: {
expression: string;
preferredExtractorId: DataExtractorId | undefined;
}) {
return this.config.getFinalExpression({
expression,
preferredExtractorId,
});
}
}

View File

@@ -1,4 +1,7 @@
import { DataExtractionResult } from "@hediet/debug-visualizer-data-extraction";
import {
DataExtractionResult,
DataExtractorId,
} from "@hediet/debug-visualizer-data-extraction";
import { VsCodeDebugSession } from "../../VsCodeDebugger";
export interface DataExtractionProviderFactory {
@@ -18,6 +21,6 @@ export interface DataExtractionProvider {
export interface DataExtractionProviderArgs {
expression: string;
preferredExtractor: string | undefined;
preferredExtractorId: DataExtractorId | undefined;
frameId: number | undefined;
}

View File

@@ -1,8 +1,6 @@
import {
DataResult,
DataExtractionResult,
ExtractedData,
isExtractedData,
DataExtractorId,
} from "@hediet/debug-visualizer-data-extraction";
import { VsCodeDebugSession } from "../../VsCodeDebugger";
import {
@@ -10,6 +8,7 @@ import {
DataExtractionProvider,
DataExtractionProviderArgs,
} from "./DataExtractionProvider";
import { parseEvaluationResultFromGenericDebugAdapter } from "./parseEvaluationResultFromGenericDebugAdapter";
export class GenericDataExtractionProviderFactory
implements DataExtractionProviderFactory {
@@ -20,47 +19,46 @@ export class GenericDataExtractionProviderFactory
}
}
class GenericDataExtractionProvider implements DataExtractionProvider {
export class GenericDataExtractionProvider implements DataExtractionProvider {
constructor(private readonly session: VsCodeDebugSession) {}
public async evaluate({
expression,
preferredExtractor,
preferredExtractorId,
frameId,
}: DataExtractionProviderArgs): Promise<
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: string }
> {
const finalExpression = this.getFinalExpression({
expression,
preferredExtractorId,
});
let reply;
try {
const reply = await this.session.evaluate({
expression,
reply = await this.session.evaluate({
expression: finalExpression,
frameId,
context: this.getContext(),
});
const resultStr = reply.result;
const jsonData = resultStr.substr(1, resultStr.length - 2);
const result = JSON.parse(jsonData) as ExtractedData;
if (!isExtractedData(result)) {
throw new Error("Invalid Data");
}
return {
kind: "data",
result: {
availableExtractors: [],
usedExtractor: {
id: "generic" as any,
name: "Generic",
priority: 1,
},
data: result,
},
};
} catch (error) {
return {
kind: "error",
message: error.message,
};
}
return parseEvaluationResultFromGenericDebugAdapter(reply.result);
}
protected getFinalExpression(args: {
expression: string;
preferredExtractorId: DataExtractorId | undefined;
}): string {
return args.expression;
}
protected getContext(): "watch" | "repl" {
return "watch";
}
}

View File

@@ -35,7 +35,7 @@ class JsDataEvaluator implements DataExtractionProvider {
public async evaluate({
expression,
preferredExtractor,
preferredExtractorId,
frameId,
}: DataExtractionProviderArgs): Promise<
| { kind: "data"; result: DataExtractionResult }
@@ -43,8 +43,8 @@ class JsDataEvaluator implements DataExtractionProvider {
> {
while (true) {
try {
const preferredExtractorExpr = preferredExtractor
? `"${preferredExtractor}"`
const preferredExtractorExpr = preferredExtractorId
? `"${preferredExtractorId}"`
: "undefined";
const body = `${getExpressionForDataExtractorApi()}.getData(

View File

@@ -1,12 +1,6 @@
export * from "./DataExtractionProvider";
import { ComposedDataExtractionProviderFactory } from "./ComposedDataExtractionProviderFactory";
import { JsDataExtractionProviderFactory } from "./JsDataExtractionProviderFactory";
import { GenericDataExtractionProviderFactory } from "./GenericDataExtractionProviderFactory";
export const defaultDataExtractionProviderFactory = new ComposedDataExtractionProviderFactory(
[
new JsDataExtractionProviderFactory(),
new GenericDataExtractionProviderFactory(),
]
);
export { ComposedDataExtractionProviderFactory } from "./ComposedDataExtractionProviderFactory";
export { JsDataExtractionProviderFactory } from "./JsDataExtractionProviderFactory";
export { GenericDataExtractionProviderFactory } from "./GenericDataExtractionProviderFactory";
export { ConfiguredDataExtractionProviderFactory } from "./ConfiguredDataExtractionProviderFactory";

View File

@@ -0,0 +1,76 @@
import {
DataExtractionResult,
isExtractedData,
} from "@hediet/debug-visualizer-data-extraction";
export function parseEvaluationResultFromGenericDebugAdapter(
resultText: string
):
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: string } {
const jsonData = resultText.trim();
let resultObj;
try {
try {
let jsonData2;
// Remove optionally enclosing characters.
if (
isEnclosedWith(jsonData, '"') ||
isEnclosedWith(jsonData, "'")
) {
// In case of JavaScript: `"{ "kind": { ... }, "text": "some\ntext" }"`
jsonData2 = jsonData.substr(1, jsonData.length - 2);
} else {
// Just in case no quoting is done.
jsonData2 = jsonData;
}
resultObj = parseJson(jsonData2);
} catch (e) {
// in case of C++: `"{ \"kind\": { ... }, \"text\": \"some\\ntext\" }"`
const str = parseJson(jsonData);
// str is now `{ "kind": { ... }, "text": "some\ntext" }"`
resultObj = parseJson(str);
// result is now { kind: { ... }, text: "some\ntext" }
}
if (!isExtractedData(resultObj)) {
return {
kind: "error",
message: "Data does not match ExtractedData interface.",
};
}
} catch (e) {
return {
kind: "error",
message: e.message,
};
}
return {
kind: "data",
result: {
availableExtractors: [],
usedExtractor: {
id: "generic" as any,
name: "Generic",
priority: 1,
},
data: resultObj,
},
};
}
function isEnclosedWith(str: string, char: string): boolean {
return str.startsWith(char) && str.endsWith(char);
}
function parseJson(str: string) {
try {
return JSON.parse(str);
} catch (error) {
throw new Error(
`Could not parse \`${str}\` as JSON.\n${error.message}`
);
}
}

View File

@@ -1,8 +1,5 @@
import { DataExtractorId } from "@hediet/debug-visualizer-data-extraction";
import {
DataExtractionState,
CompletionItem,
} from "@hediet/debug-visualizer-vscode-shared";
import { DataExtractionState, CompletionItem } from "../contract";
export interface DataSource {
createEvaluationWatcher(

View File

@@ -6,10 +6,7 @@ import {
import { observable, autorun, action } from "mobx";
import { Disposable } from "@hediet/std/disposable";
import { DataExtractorId } from "@hediet/debug-visualizer-data-extraction";
import {
DataExtractionState,
CompletionItem,
} from "@hediet/debug-visualizer-vscode-shared";
import { DataExtractionState, CompletionItem } from "../contract";
import { hotClass } from "@hediet/node-reload";
import { VsCodeDebuggerView } from "../VsCodeDebugger";
import { DataExtractionProviderFactory } from "./DataExtractionProvider/DataExtractionProvider";
@@ -76,7 +73,7 @@ export class DataSourceImpl implements DataSource {
const result = await extractionProvider.evaluate({
expression: w.expression,
frameId,
preferredExtractor: w.preferredDataExtractor,
preferredExtractorId: w.preferredDataExtractor,
});
w._state = result;

View File

@@ -1,17 +0,0 @@
import { Disposable } from "@hediet/std/disposable";
import { VsCodeDebugger, VsCodeDebuggerView } from "../VsCodeDebugger";
import { DataSourceImpl } from "./DataSourceImpl";
import { defaultDataExtractionProviderFactory } from "./DataExtractionProvider";
export class Sources {
public readonly dispose = Disposable.fn();
private readonly debugger = this.dispose.track(new VsCodeDebugger());
private readonly debuggerView = this.dispose.track(
new VsCodeDebuggerView(this.debugger)
);
public readonly dataSource = new DataSourceImpl(
this.debuggerView,
defaultDataExtractionProviderFactory
);
}

View File

@@ -1 +1 @@
export * from "./Sources";
export * from "./DataSourceImpl";

View File

@@ -1,31 +1,37 @@
import { WebSocketStream } from "@hediet/typed-json-rpc-websocket";
import { AddressInfo } from "net";
import WebSocket = require("ws");
import { join } from "path";
import { ConnectionHandler } from "./ConnectionHandler";
import { Sources } from "./DataSource";
import * as express from "express";
import * as http from "http";
import * as serveStatic from "serve-static";
import { Config } from "./Config";
import cryptoRandomString = require("crypto-random-string");
import { distPath } from "debug-visualizer-webview";
import { DataSource } from "./DataSource/DataSource";
export class Server {
private server: http.Server;
public readonly secret = cryptoRandomString({ length: 20 });
constructor(sources: Sources, config: Config) {
constructor(dataSource: DataSource, config: Config) {
const app = express();
const distPath = join(__dirname, "../ui/dist");
app.use(serveStatic(distPath));
this.server = app.listen();
console.log(
`Serving "${distPath}" on port ${
(this.server.address() as AddressInfo).port
}`
);
const wss = new WebSocket.Server({ server: this.server });
wss.on("connection", ws => {
const stream = new WebSocketStream(ws);
new ConnectionHandler(
sources.dataSource,
dataSource,
stream,
this,
config,

View File

@@ -1,7 +1,7 @@
import { Disposable } from "@hediet/std/disposable";
import { debug, DebugSession } from "vscode";
import { EventEmitter } from "@hediet/std/events";
import { CompletionItem } from "@hediet/debug-visualizer-vscode-shared";
import { CompletionItem } from "./contract";
import { observable, runInAction } from "mobx";
export class VsCodeDebugger {
@@ -149,6 +149,9 @@ export class VsCodeDebugSession {
frameId: args.frameId,
column: args.column,
});
if (!reply) {
return [];
}
return reply.targets;
} catch (error) {
console.error(error);
@@ -159,11 +162,12 @@ export class VsCodeDebugSession {
public async evaluate(args: {
expression: string;
frameId: number | undefined;
context?: "watch" | "repl";
}): Promise<{ result: string }> {
const reply = await this.session.customRequest("evaluate", {
expression: args.expression,
frameId: args.frameId,
context: "watch",
context: args.context || "watch",
});
return { result: reply.result };
}

View File

@@ -15,14 +15,35 @@ registerUpdateReconciler(module);
import { WebViews } from "./WebViews";
import { Server } from "./Server";
import { Config } from "./Config";
import { Sources } from "./DataSource";
import { VsCodeDebugger, VsCodeDebuggerView } from "./VsCodeDebugger";
import { DataSourceImpl } from "./DataSource";
import {
ComposedDataExtractionProviderFactory,
JsDataExtractionProviderFactory,
GenericDataExtractionProviderFactory,
ConfiguredDataExtractionProviderFactory,
} from "./DataSource/DataExtractionProvider";
export class Extension {
public dispose = Disposable.fn();
public readonly dispose = Disposable.fn();
private readonly config = new Config();
private readonly sources = this.dispose.track(new Sources());
private readonly server = new Server(this.sources, this.config);
private readonly debugger = this.dispose.track(new VsCodeDebugger());
private readonly debuggerView = this.dispose.track(
new VsCodeDebuggerView(this.debugger)
);
public readonly dataSource = new DataSourceImpl(
this.debuggerView,
new ComposedDataExtractionProviderFactory([
new ConfiguredDataExtractionProviderFactory(this.config),
new JsDataExtractionProviderFactory(),
new GenericDataExtractionProviderFactory(),
])
);
private readonly server = new Server(this.dataSource, this.config);
private readonly views = this.dispose.track(new WebViews(this.server));
constructor() {

View File

@@ -4,3 +4,7 @@ declare namespace NodeJS {
USE_DEV_UI?: "true";
}
}
declare module "debug-visualizer-webview" {
export const distPath: string;
}

View File

@@ -2,6 +2,7 @@ import * as webpack from "webpack";
import path = require("path");
import { CleanWebpackPlugin } from "clean-webpack-plugin";
import CopyPlugin = require("copy-webpack-plugin");
import { readFileSync } from "fs";
const r = (file: string) => path.resolve(__dirname, file);
@@ -19,6 +20,7 @@ module.exports = {
vscode: "commonjs vscode",
"@hediet/debug-visualizer-data-extraction":
"@hediet/debug-visualizer-data-extraction",
"debug-visualizer-webview": "debug-visualizer-webview",
},
resolve: {
extensions: [".ts", ".js"],
@@ -41,14 +43,22 @@ module.exports = {
},
plugins: [
new CleanWebpackPlugin(),
new CopyPlugin([
{
from: r("../data-extraction/"),
to: r(
"./dist/node_modules/@hediet/debug-visualizer-data-extraction/"
),
ignore: ["**/node_modules/**/*"],
},
]),
includeDependency(r("../data-extraction/")),
includeDependency(r("../webview/")),
],
} as webpack.Configuration;
function includeDependency(location: string) {
const content = readFileSync(path.join(location, "package.json"), {
encoding: "utf8",
});
const pkgName = JSON.parse(content).name;
return new CopyPlugin([
{
from: location,
to: r(`./dist/node_modules/${pkgName}`),
ignore: ["**/node_modules/**/*"],
},
]);
}

View File

@@ -1,9 +1,14 @@
{
"private": true,
"workspaces": [
"./shared",
"./data-extraction",
"./extension",
"./extension/ui"
]
"./webview"
],
"scripts": {
"build": "yarn build-data-extraction && yarn build-extension && yarn build-ui",
"build-data-extraction": "yarn workspace @hediet/debug-visualizer-data-extraction build",
"build-extension": "yarn workspace debug-visualizer build",
"build-ui": "yarn workspace debug-visualizer-webview build"
}
}

View File

@@ -1,23 +0,0 @@
{
"name": "@hediet/debug-visualizer-vscode-shared",
"private": true,
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {
"name": "Henning Dieterichs",
"email": "henning.dieterichs@live.de"
},
"license": "MIT",
"files": [
"dist",
"src"
],
"scripts": {
"dev": "tsc --watch"
},
"dependencies": {
"@hediet/std": "^0.6.0",
"@hediet/typed-json-rpc": "^0.7.7"
}
}

View File

@@ -1 +0,0 @@
export * from "./contract";

View File

@@ -1,16 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"strict": true,
"outDir": "dist",
"skipLibCheck": true,
"rootDir": "./src",
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"newLine": "LF",
"sourceMap": true
},
"include": ["./src/**/*"]
}

5
webview/index.js Normal file
View File

@@ -0,0 +1,5 @@
// This is the entry point when this package is used as library from the extension.
// This package MUST NOT be bundled.
const path = require("path");
module.exports.distPath = path.join(__dirname, "dist");

View File

@@ -1,18 +1,19 @@
{
"name": "debug-visualizer-ui",
"name": "debug-visualizer-webview",
"version": "0.0.1",
"scripts": {
"dev": "webpack-dev-server --hot",
"dev-playground": "webpack-dev-server --hot --port 8090 --playground",
"build": "webpack"
},
"main": "./index.js",
"dependencies": {
"@blueprintjs/core": "^3.23.1",
"@hediet/std": "^0.6.0",
"blueprintjs": "^0.0.8",
"classnames": "^2.2.6",
"mobx": "^5.15.4",
"mobx-react": "^6.1.7",
"mobx-react": "^6.1.8",
"monaco-editor": "^0.20.0",
"popper.js": "^1.16.1",
"react": "^16.12.0",
@@ -21,28 +22,29 @@
"react-svg-pan-zoom": "^3.8.0",
"viz.js": "^2.1.2",
"line-column": "^1.0.2",
"vis-network": "^7.3.4",
"vis-data": "^6.3.5",
"vis-network": "^7.3.6",
"vis-data": "^6.4.1",
"react-plotly.js": "^2.4.0",
"plotly.js": "^1.52.2"
"plotly.js": "^1.52.2",
"@hediet/debug-visualizer-data-extraction": "*"
},
"devDependencies": {
"@types/plotly.js": "^1.44.28",
"@types/plotly.js": "1.44.28",
"@types/react-plotly.js": "^2.2.4",
"@types/html-webpack-plugin": "^3.2.2",
"@types/react-measure": "^2.0.6",
"@types/react-svg-pan-zoom": "^3.3.0",
"@types/webpack": "^4.41.6",
"@types/classnames": "^2.2.9",
"@types/react": "^16.9.19",
"@types/react": "^16.9.22",
"@types/react-dom": "^16.9.5",
"@types/line-column": "^1.0.0",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"file-loader": "^5.0.2",
"fork-ts-checker-webpack-plugin": "^4.0.3",
"file-loader": "^5.1.0",
"fork-ts-checker-webpack-plugin": "^4.0.4",
"html-webpack-plugin": "^3.2.0",
"monaco-editor-webpack-plugin": "^1.8.2",
"monaco-editor-webpack-plugin": "^1.9.0",
"node-sass": "^4.13.1",
"raw-loader": "^4.0.0",
"sass": "^1.25.0",
@@ -50,7 +52,7 @@
"style-loader": "^1.1.3",
"ts-loader": "^6.2.1",
"ts-node": "^8.6.2",
"typescript": "^3.7.5",
"typescript": "^3.8.2",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"

View File

@@ -1,5 +1,5 @@
import React = require("react");
import { Model } from "../Model/Model";
import { Model } from "../model/Model";
import { observer, disposeOnUnmount } from "mobx-react";
import { observable, action, autorun } from "mobx";
import * as monaco from "monaco-editor";

View File

@@ -2,7 +2,7 @@ import React = require("react");
import { Button, Spinner } from "@blueprintjs/core";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
import { Model } from "../Model/Model";
import { Model } from "../model/Model";
import { ExpressionInput } from "./ExpressionInput";
import { Visualizer } from "./Visualizer";
import classnames = require("classnames");

View File

@@ -1,5 +1,5 @@
import React = require("react");
import { Model } from "../Model/Model";
import { Model } from "../model/Model";
import { observer } from "mobx-react";
import { NoData } from "./NoData";

View File

@@ -3,8 +3,8 @@ import { Popover } from "@blueprintjs/core";
import { DataExtractorInfo } from "@hediet/debug-visualizer-data-extraction";
import { computed } from "mobx";
import { observer } from "mobx-react";
import { Model } from "../Model/Model";
import { VisualizationId } from "../Visualizers/Visualizer";
import { Model } from "../model/Model";
import { VisualizationId } from "../visualizers/Visualizer";
@observer
export class VisualizerHeaderDetails extends React.Component<{ model: Model }> {
@@ -42,12 +42,14 @@ export class VisualizerHeaderDetails extends React.Component<{ model: Model }> {
className="component-VisualizerHeaderDetails"
style={{ display: "flex", alignItems: "center" }}
>
<NamedSelect
name="Source"
selected={0}
options={[{ label: "js" }]}
onSelected={item => {}}
/>
{/*
<NamedSelect
name="Source"
selected={0}
options={[{ label: "js" }]}
onSelected={item => {}}
/>
*/}
<div style={{ width: 10 }} />
<NamedSelect

View File

@@ -1,8 +1,8 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
import "./style.scss";
import { Model } from "./Model/Model";
import Components = require("./Components/GUI");
import { Model } from "./model/Model";
import Components = require("./components/GUI");
const model = new Model();
@@ -15,7 +15,7 @@ if (model.runningMode !== "webView") {
}
function render(target: HTMLDivElement) {
const c = require("./Components/GUI") as typeof Components;
const c = require("./components/GUI") as typeof Components;
ReactDOM.render(<c.GUI model={model} />, target);
}
@@ -31,7 +31,7 @@ declare var module: {
declare var require: (name: string) => any;
if (module.hot) {
module.hot.accept("./Components/GUI", () => {
module.hot.accept("./components/GUI", () => {
render(target);
});
}

View File

@@ -1,13 +1,13 @@
import {
debugVisualizerUIContract,
DataExtractionState,
} from "@hediet/debug-visualizer-vscode-shared";
} from "debug-visualizer/src/contract";
import { WebSocketStream } from "@hediet/typed-json-rpc-websocket";
import { ConsoleRpcLogger } from "@hediet/typed-json-rpc";
import { observable, action, computed, when, autorun } from "mobx";
import { DataExtractorId } from "@hediet/debug-visualizer-data-extraction";
import { Visualization, VisualizationId } from "../Visualizers/Visualizer";
import { knownVisualizations } from "../Visualizers";
import { Visualization, VisualizationId } from "../visualizers/Visualizer";
import { knownVisualizations } from "../visualizers";
import { getApi as getVsCodeApi } from "./VsCodeApi";
import { MonacoBridge } from "./MonacoBridge";
import { Disposable } from "@hediet/std/disposable";

View File

@@ -1,6 +1,6 @@
import React = require("react");
import "../style.scss";
import { DecoratedGridComponent } from "../Visualizers/GridVisualizer";
import { DecoratedGridComponent } from "../visualizers/GridVisualizer";
import { observable } from "mobx";
import { observer } from "mobx-react";

View File

@@ -8,13 +8,13 @@ import {
isCommonDataType,
CommonDataTypes,
} from "@hediet/debug-visualizer-data-extraction";
import { createTreeViewModelFromTreeNodeData } from "./TreeVisualizer/Visualizer";
import { createTreeViewModelFromTreeNodeData } from "./TreeVisualizer/TreeVisualizer";
import { TreeWithPathView, TreeViewModel } from "./TreeVisualizer/Views";
import React = require("react");
import { observer, disposeOnUnmount } from "mobx-react";
import { observable, autorun, trace } from "mobx";
import * as monaco from "monaco-editor";
import { getLanguageId } from "./TextVisualizer/MonacoTextVisualizer";
import { getLanguageId } from "./text-visualizers/MonacoTextVisualizer";
import LineColumn = require("line-column");
export class AstVisualizer extends VisualizationProvider {

View File

@@ -16,6 +16,25 @@ import {
} from "../Visualizer";
import React = require("react");
export class TreeVisualizer extends VisualizationProvider {
getVisualizations(
data: ExtractedData,
collector: VisualizationCollector
): void {
if (isCommonDataType(data, { tree: true })) {
collector.addVisualization({
id: asVisualizationId("tree"),
name: "Tree",
priority: 100,
render() {
const m = createTreeViewModelFromTreeNodeData(data.root);
return <TreeWithPathView model={m} />;
},
});
}
}
}
export function createTreeViewModelFromTreeNodeData<TData>(
root: TreeNode<TData>
): TreeViewModel<TData> {
@@ -46,22 +65,3 @@ export function createTreeViewModelFromTreeNodeData<TData>(
return model;
}
}
export class TreeVisualizer extends VisualizationProvider {
getVisualizations(
data: ExtractedData,
collector: VisualizationCollector
): void {
if (isCommonDataType(data, { tree: true })) {
collector.addVisualization({
id: asVisualizationId("tree"),
name: "Tree",
priority: 100,
render() {
const m = createTreeViewModelFromTreeNodeData(data.root);
return <TreeWithPathView model={m} />;
},
});
}
}
}

View File

@@ -2,8 +2,8 @@ import { observer, disposeOnUnmount } from "mobx-react";
import { observable, autorun, computed, action, runInAction } from "mobx";
import React = require("react");
import classNames = require("classnames");
import { Rectangle, Point } from "../../Components/Point";
import { SvgLine } from "../../Components/SvgElements";
import { Rectangle, Point } from "../../components/Point";
import { SvgLine } from "../../components/SvgElements";
import "./style.scss";
export class TreeViewModel<TData = unknown> {

View File

@@ -1,13 +1,13 @@
import "./style.scss";
import { ComposedVisualizationProvider } from "./Visualizer";
import { TreeVisualizer } from "./TreeVisualizer/Visualizer";
import { GraphvizGraphVisualizer } from "./GraphVisualizer/GraphvizGraphVisualizer";
import { TreeVisualizer } from "./TreeVisualizer/TreeVisualizer";
import { GraphvizGraphVisualizer } from "./graph-visualizers/GraphvizGraphVisualizer";
import { SvgVisualizer } from "./SvgVisualizer";
import { GraphvizDotVisualizer } from "./GraphVisualizer/GraphvizDotVisualizer";
import { TextVisualizer } from "./TextVisualizer/TextVisualizer";
import { MonacoTextVisualizer } from "./TextVisualizer/MonacoTextVisualizer";
import { GraphvizDotVisualizer } from "./graph-visualizers/GraphvizDotVisualizer";
import { TextVisualizer } from "./text-visualizers/TextVisualizer";
import { MonacoTextVisualizer } from "./text-visualizers/MonacoTextVisualizer";
import { AstVisualizer } from "./AstVisualizer";
import { VisJsGraphVisualizer } from "./GraphVisualizer/VisJsGraphVisualizer";
import { VisJsGraphVisualizer } from "./graph-visualizers/VisJsGraphVisualizer";
import { PlotlyVisualizer } from "./PlotlyVisualizer";
import { GridVisualizer } from "./GridVisualizer";

View File

@@ -47,7 +47,12 @@ module.exports = {
new CleanWebpackPlugin(),
];
if (mode === "default") {
plugins.push(new MonacoWebpackPlugin());
plugins.push(
new MonacoWebpackPlugin({
// Add more languages here once webworker issues are solved.
languages: ["typescript"],
})
);
}
return plugins;
})(),

197
yarn.lock
View File

@@ -77,10 +77,10 @@
stacktracey "^1.2.112"
ws "^7.0.0"
"@hediet/node-reload@^0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@hediet/node-reload/-/node-reload-0.7.2.tgz#d2b946e971ac7a2732704f2ede07a78401322187"
integrity sha512-RG35DwaKCgcw7RSQt+CI/3uGGkOn/K05qhIiktYVGnTshJn+ZWAtPUtp3bWAMQo5dxCWzw9IoIMh0az6/o8diw==
"@hediet/node-reload@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@hediet/node-reload/-/node-reload-0.7.3.tgz#305d68f54185200b018b14f257037ab8d8ca9857"
integrity sha512-icOyfDpArfvqmw0VLf2CoGR/jCSuWk3fScJGFuXQHpb0c9yNoGTiuG3Q8L2iJIuDzCjRu47DR2T+yCvZsY/f+w==
dependencies:
"@hediet/live-debug" "^0.5.1"
"@hediet/std" "^0.6.0"
@@ -92,6 +92,11 @@
stack-trace "^0.0.10"
ws "^7.0.0"
"@hediet/semantic-json@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@hediet/semantic-json/-/semantic-json-0.1.0.tgz#ca3831778f1e59e555d0112decd5fe598437fdd3"
integrity sha512-lNdXabUmyxXnysXadTKyiKK9ik5L8b9SXu/QshgvE271QObPtp2Ubmh+rLNNCEAO65DE2VAxcesWmRKYfaQSJg==
"@hediet/std@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@hediet/std/-/std-0.6.0.tgz#f7d2ffc1180ecef6ff272d0d6780f0c0d9337e4e"
@@ -398,17 +403,17 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c"
integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==
"@types/node@^13.7.1":
version "13.7.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d"
integrity sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA==
"@types/node@^13.7.4":
version "13.7.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.4.tgz#76c3cb3a12909510f52e5dc04a6298cdf9504ffd"
integrity sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw==
"@types/node@^8.0.7":
version "8.10.51"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.51.tgz#80600857c0a47a8e8bafc2dae6daed6db58e3627"
integrity sha512-cArrlJp3Yv6IyFT/DYe+rlO8o3SIHraALbBW/+CcCYW/a9QucpLI+n2p4sRxAvl2O35TiecpX2heSZtJjvEO+Q==
"@types/plotly.js@*", "@types/plotly.js@^1.44.28":
"@types/plotly.js@*", "@types/plotly.js@1.44.28":
version "1.44.28"
resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-1.44.28.tgz#e43afd646f2e93f9080b062d3cb7b578ae926f46"
integrity sha512-Ajvtn6QHjLMZfRySd0L7f17ONKxiYpZSzW29sx/bU9KL/pzbu+pXdfNika9n+W0G1ScLEJEtI2yBsZXT1UXDKA==
@@ -462,10 +467,10 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/react@^16.9.19":
version "16.9.19"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40"
integrity sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A==
"@types/react@^16.9.22":
version "16.9.22"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.22.tgz#f0288c92d94e93c4b43e3f5633edf788b2c040ae"
integrity sha512-7OSt4EGiLvy0h5R7X+r0c7S739TCU/LvWbkNOrm10lUwNHe7XPz5OLhLOSZeCkqO9JSCly1NkYJ7ODTUqVnHJQ==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"
@@ -518,10 +523,10 @@
dependencies:
source-map "^0.6.1"
"@types/vscode@^1.35.0":
version "1.42.0"
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.42.0.tgz#0ad891a9487e91e34be7c56985058a179031eb76"
integrity sha512-ds6TceMsh77Fs0Mq0Vap6Y72JbGWB8Bay4DrnJlf5d9ui2RSe1wis13oQm+XhguOeH1HUfLGzaDAoupTUtgabw==
"@types/vscode@1.35.0":
version "1.35.0"
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.35.0.tgz#b17526ef1e9df5cbf7253be6765a33fd518a2304"
integrity sha512-Iyliuu8Hv4qy4TEaevQzChh9UsTEcuaKdcHXBbvJnoJSF5Td2yNENOrPK+vuOaXJJBhQZb4BNJKOxt6caaQR8A==
"@types/webpack-sources@*":
version "0.1.6"
@@ -1659,10 +1664,10 @@ chownr@^1.1.1:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6"
integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==
chrome-launcher@^0.11.2:
version "0.11.2"
resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.11.2.tgz#c9a248dbccd3a08565553acf61adff879bcc982c"
integrity sha512-jx0kJDCXdB2ARcDMwNCtrf04oY1Up4rOmVu+fqJ5MTPOOIG8EhRcEU9NZfXZc6dMw9FU8o1r21PNp8V2M0zQ+g==
chrome-launcher@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.12.0.tgz#08db81ef0f7b283c331df2c350e780c38bd0ce3a"
integrity sha512-rBUP4tvWToiileDi3UR0SbWKoUoDCYTRmVND2sdoBL1xANBgVz8V9h1yQluj3MEQaBJg0fRw7hW82uOPrJus7A==
dependencies:
"@types/node" "*"
is-wsl "^2.1.0"
@@ -2796,6 +2801,11 @@ emojis-list@^2.0.0:
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@@ -2901,6 +2911,11 @@ es6-iterator@^2.0.3, es6-iterator@~2.0.3:
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-object-assign@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=
es6-promise@^3.0.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
@@ -3248,12 +3263,12 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
file-loader@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.0.2.tgz#7f3d8b4ac85a5e8df61338cfec95d7405f971caa"
integrity sha512-QMiQ+WBkGLejKe81HU8SZ9PovsU/5uaLo0JdTCEXOYv7i7jfAjHZi1tcwp9tSASJPOmmHZtbdCervFmXMH/Dcg==
file-loader@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.1.0.tgz#cb56c070efc0e40666424309bd0d9e45ac6f2bb8"
integrity sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==
dependencies:
loader-utils "^1.2.3"
loader-utils "^1.4.0"
schema-utils "^2.5.0"
fill-range@^4.0.0:
@@ -3391,10 +3406,10 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
fork-ts-checker-webpack-plugin@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.0.3.tgz#958f4e4ec3e7fd9d4ad5a50a4442abce77dca19a"
integrity sha512-5hGeMYKg817Hp6rvdc2EOS/T/Cq0JW9LLJDZtVUPlNIojIuP7YbOAdrHEk4Irw1097YQUr56kWIiYhqNPzfNzQ==
fork-ts-checker-webpack-plugin@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.0.4.tgz#ba1be68d63dcf509f6d1b08fb8e19efb6d7e8a96"
integrity sha512-6IEqHH6s+tv5sho5d3dn7dfcnbjKHwfqL74kRfpAP2e8MCHuMh5ixtYrbdfPO4Zat3S5gwULOoVArjK3HMwNdA==
dependencies:
babel-code-frame "^6.22.0"
chalk "^2.4.1"
@@ -4654,7 +4669,7 @@ internal-ip@^4.3.0:
default-gateway "^4.2.0"
ipaddr.js "^1.9.0"
interpret@1.2.0:
interpret@1.2.0, interpret@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
@@ -4828,6 +4843,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
is-docker@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b"
integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==
is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
@@ -5012,6 +5032,11 @@ is-wsl@^2.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.0.tgz#94369bbeb2249ef07b831b1b08590e686330ccbb"
integrity sha512-pFTjpv/x5HRj8kbZ/Msxi9VrvtOMRBqaDi3OIcbwPI3OuH+r3lLxVWukLITBaOGJIbA/w2+M1eVmVa4XNQlAmQ==
is-wsl@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d"
integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
@@ -5256,6 +5281,15 @@ loader-utils@^0.2.16:
json5 "^0.5.0"
object-assign "^4.0.1"
loader-utils@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
dependencies:
big.js "^5.2.2"
emojis-list "^3.0.0"
json5 "^1.0.1"
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -5664,10 +5698,10 @@ mobx-react-lite@^1.4.2:
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-1.5.2.tgz#c4395b0568b9cb16f07669d8869cc4efa1b8656d"
integrity sha512-PyZmARqqWtpuQaAoHF5pKX7h6TKNLwq6vtovm4zZvG6sEbMRHHSqioGXSeQbpRmG8Kw8uln3q/W1yMO5IfL5Sg==
mobx-react@^6.1.7:
version "6.1.7"
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.1.7.tgz#2fe620851ef33df38e50645101321830a07fc4e2"
integrity sha512-TXwqweY7yEbMl+0F5jOO5bHWUbgeNJr8o1or+1NdhWWg6duIqsGW1D6ojNmn2RO27vRJHkZrp4kjv6919nHS0A==
mobx-react@^6.1.8:
version "6.1.8"
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.1.8.tgz#5b9a3950463d58c154dda2c94d16d48ed8fcb02e"
integrity sha512-NCMJn/hrWoeyeNbzCsBDtftWSy6VlFgw1VzhogrciPFvJIl2xs+8rJJdPlRHQTiNirwNoHNKJgUE4WhPZPvKDw==
dependencies:
mobx-react-lite "^1.4.2"
@@ -5681,10 +5715,10 @@ mobx@^5.15.4:
resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.4.tgz#9da1a84e97ba624622f4e55a0bf3300fb931c2ab"
integrity sha512-xRFJxSU2Im3nrGCdjSuOTFmxVDGeqOHL+TyADCGbT0k4HHqGmx5u2yaHNryvoORpI4DfbzjJ5jPmuv+d7sioFw==
monaco-editor-webpack-plugin@^1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.8.2.tgz#3721b8d9a3e2e41b154cf2a2955a7d7246c03714"
integrity sha512-g9G7A/lxQtpPsYaZFBqm73dwVkOziGUXExIR6iW7ksZUaiMkpvdTiE9O8edgdJGo+XtCmjycmIKB1Lt8VKbSTQ==
monaco-editor-webpack-plugin@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.0.tgz#5b547281b9f404057dc5d8c5722390df9ac90be6"
integrity sha512-tOiiToc94E1sb50BgZ8q8WK/bxus77SRrwCqIpAB5er3cpX78SULbEBY4YPOB8kDolOzKRt30WIHG/D6gz69Ww==
dependencies:
loader-utils "^1.2.3"
@@ -6247,12 +6281,13 @@ once@~1.3.0:
dependencies:
wrappy "1"
open@^6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9"
integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==
open@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/open/-/open-7.0.2.tgz#fb3681f11f157f2361d2392307548ca1792960e8"
integrity sha512-70E/pFTPr7nZ9nLDPNTcj3IVqnNvKuP4VsBmoKV9YGTnChe0mlS3C4qM7qKarhZ8rGaHKLfo+vBTHXDp6ZSyLQ==
dependencies:
is-wsl "^1.1.0"
is-docker "^2.0.0"
is-wsl "^2.1.1"
opn@^5.5.0:
version "5.5.0"
@@ -7267,6 +7302,13 @@ readdirp@^3.1.1:
dependencies:
picomatch "^2.0.4"
rechoir@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
dependencies:
resolve "^1.1.6"
redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -7556,7 +7598,7 @@ resolve@^0.6.1:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46"
integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY=
resolve@^1.0.0, resolve@^1.1.5:
resolve@^1.0.0, resolve@^1.1.5, resolve@^1.1.6:
version "1.15.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
@@ -7954,6 +7996,24 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
shelljs@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
dependencies:
glob "^7.0.0"
interpret "^1.0.0"
rechoir "^0.6.2"
shx@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.2.tgz#40501ce14eb5e0cbcac7ddbd4b325563aad8c123"
integrity sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA==
dependencies:
es6-object-assign "^1.0.3"
minimist "^1.2.0"
shelljs "^0.8.1"
signal-exit@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@@ -8973,10 +9033,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^3.7.5:
version "3.7.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
typescript@^3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.2.tgz#91d6868aaead7da74f493c553aeff76c0c0b1d5a"
integrity sha512-EgOVgL/4xfVrCMbhYKUQTdF37SQn4Iw73H5BgCrF1Abdun7Kwy/QZsE/ssAy0y4LxBbvua3PIbFsbRczWWnDdQ==
uglify-js@3.4.x:
version "3.4.10"
@@ -9321,28 +9381,22 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vis-data@^6.3.5:
version "6.3.5"
resolved "https://registry.yarnpkg.com/vis-data/-/vis-data-6.3.5.tgz#db53cb0828601aa0908f86eca1cfe80f69f17873"
integrity sha512-H8lD1NTmC5HimYeqTouxhbUya5qrYQGjpJhIHkxsm5R34EEdcm/D1cLTMLFFyIoZC6SQkADQj+dlFKf5DOnSww==
vis-data@^6.4.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/vis-data/-/vis-data-6.4.1.tgz#2ee74ae3b376d3b911751a168c16b3d97c3fbca7"
integrity sha512-kFCFQg1adQbC1hDMKtNLaLjYUe4hCDhg2/iqM6qAFvLu0x58IDolZwBluMJuaJfhU3ScC2W1higqglIWNKIJeQ==
optionalDependencies:
vis-util "2.0.1"
vis-uuid "1.1.3"
vis-util "3.0.0"
vis-network@^7.3.4:
version "7.3.4"
resolved "https://registry.yarnpkg.com/vis-network/-/vis-network-7.3.4.tgz#818ccf7d82afffae7059e6b2cb520cd28ea01070"
integrity sha512-4hfB1DDnzclUUdniBh2WN2agcCmrL2ERmWsRB8wv8XtiiQ+Gg6HNzx5v7xySRWK+yH88LVnrrzaM+mDb5jcQtg==
vis-network@^7.3.6:
version "7.3.6"
resolved "https://registry.yarnpkg.com/vis-network/-/vis-network-7.3.6.tgz#b0fe0a2a4fea027327f15fe095e395d2ec81c305"
integrity sha512-XmcjZaKmwEuDMUkcOV1zDaQOo6ANVwIlAfFDSEtOkWbUi34sZLYbxhpr4UFPYxpQA//TnNC9Rgvoivt7uqdxTw==
vis-util@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/vis-util/-/vis-util-2.0.1.tgz#4538aee119795bde1f7996a3ee8e0148baf71124"
integrity sha512-VBQ6zCT+Iaum70uzLbjk0nLMOjp9NhPzU42j0gaM6q6tg0eTcgIWNXzAqamhQtmm1kDj0jMLzKvkFOPENYv34w==
vis-uuid@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/vis-uuid/-/vis-uuid-1.1.3.tgz#2f53ff35e9e026b0ec93bc433ce685c40c2f784c"
integrity sha512-2B6XdY1bkzbUh+TugmnAaFa61KO9R5pzBzIuFIm8a9FrkbxIdSmQXV+FbfkL8QunkQV/bT0JDLQ2puqCS2+0Og==
vis-util@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/vis-util/-/vis-util-3.0.0.tgz#9b0da1e86e9beb5fbea17f5af3a49263c48d7c87"
integrity sha512-1B66y7E1Trc+SBjR8zhEULa4NzmPLitZoYoyw685Xi9CYn5UyJrNIB9TI/MAnwN+UioSQ4ogDQYOtO501CjREg==
viz.js@^2.1.2:
version "2.1.2"
@@ -9623,13 +9677,18 @@ ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
ws@^7.0.0, ws@^7.1.1:
ws@^7.0.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.1.1.tgz#f9942dc868b6dffb72c14fd8f2ba05f77a4d5983"
integrity sha512-o41D/WmDeca0BqYhsr3nJzQyg9NF5X8l/UdnFNux9cS3lwB+swm8qGWX5rn+aD6xfBU3rGmtHij7g7x6LxFU3A==
dependencies:
async-limiter "^1.0.0"
ws@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.1.tgz#03ed52423cd744084b2cf42ed197c8b65a936b8e"
integrity sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"