Adds support for pwa-node and adds a poll option.

This commit is contained in:
Henning Dieterichs
2020-07-20 19:40:12 +02:00
parent e5707a0f2e
commit 5964c1c503
10 changed files with 162 additions and 77 deletions

View File

@@ -25,6 +25,7 @@ export class JsEvaluationEngine implements EvaluationEngine {
"extensionHost",
"chrome",
"pwa-chrome",
"pwa-node",
];
if (supportedDebugAdapters.indexOf(session.session.type) !== -1) {
return new JsEvaluator(session);
@@ -38,6 +39,13 @@ class JsEvaluator implements Evaluator {
constructor(private readonly session: VsCodeDebugSession) {}
private getContext(): "copy" | "repl" {
if (this.session.session.type.startsWith("pwa-")) {
return "copy";
}
return "repl";
}
public async evaluate({
expression,
preferredExtractorId,
@@ -75,10 +83,13 @@ class JsEvaluator implements Evaluator {
const reply = await this.session.evaluate({
expression: wrappedExpr,
frameId,
context: "repl",
context: this.getContext(),
});
const resultStr = reply.result;
const jsonData = resultStr.substr(1, resultStr.length - 2);
const jsonData =
this.getContext() === "copy"
? resultStr
: resultStr.substr(1, resultStr.length - 2);
const result = JSON.parse(jsonData) as DataResult;
if (result.kind === "NoExtractors") {
@@ -117,7 +128,7 @@ class JsEvaluator implements Evaluator {
await this.session.evaluate({
expression,
frameId,
context: "repl",
context: this.getContext(),
});
return true;

View File

@@ -35,9 +35,6 @@ export class VsCodeDebugger {
createDebugAdapterTracker: session => {
const extendedSession = this.getDebugSession(session);
return {
onWillReceiveMessage: msg => {
console.log(msg.type, msg.event, msg);
},
onDidSendMessage: async msg => {
type Message =
| StoppedEvent
@@ -167,7 +164,7 @@ export class VsCodeDebugSession {
public async evaluate(args: {
expression: string;
frameId: number | undefined;
context: "watch" | "repl";
context: "watch" | "repl" | "copy";
}): Promise<{ result: string }> {
const reply = await this.session.customRequest("evaluate", {
expression: args.expression,

View File

@@ -12,7 +12,7 @@ import { createTreeViewModelFromTreeNodeData } from "./TreeVisualizer/TreeVisual
import { TreeWithPathView, TreeViewModel } from "./TreeVisualizer/Views";
import * as React from "react";
import { observer, disposeOnUnmount } from "mobx-react";
import { observable, autorun, trace } from "mobx";
import { observable, autorun, trace, computed } from "mobx";
import * as monaco from "monaco-editor";
import { getLanguageId } from "./text-visualizers/MonacoTextVisualizer";
import LineColumn from "line-column";
@@ -115,80 +115,116 @@ export class MonacoEditor extends React.Component<{
}
}
@computed.struct
private get markedRanges(): monaco.IRange[] {
if (!this.editor || !this.model) {
return [];
}
const editorModel = this.model;
const ranges = this.props.model.marked.map(s =>
this.props.nodeInfoToRange(s.data)
);
return ranges;
}
@disposeOnUnmount
private _updateMarkedDecorations = autorun(
() => {
if (this.editor && this.model) {
const editorModel = this.model;
const ranges = this.props.model.marked.map(s =>
this.props.nodeInfoToRange(s.data)
if (!this.editor) {
return;
}
const ranges = this.markedRanges;
this.markedDecorations = this.editor.deltaDecorations(
this.markedDecorations,
ranges.map(range => ({
range,
options: { className: "marked" },
}))
);
if (ranges.length > 0) {
this.editor.revealRange(
ranges[0],
monaco.editor.ScrollType.Smooth
);
this.markedDecorations = this.editor.deltaDecorations(
this.markedDecorations,
ranges.map(range => ({
range,
options: { className: "marked" },
}))
);
if (ranges.length > 0) {
this.editor.revealRange(
ranges[0],
monaco.editor.ScrollType.Smooth
);
}
}
},
{ name: "updateMarkedDecorations" }
);
@computed.struct
private get selected(): monaco.IRange | undefined {
if (this.editor && this.model) {
const selected = this.props.model.selected;
if (selected) {
const range = this.props.nodeInfoToRange(selected.data);
return range;
}
}
return undefined;
}
@disposeOnUnmount
private _updateSelectedDecoration = autorun(
() => {
if (this.editor && this.model) {
const selected = this.props.model.selected;
if (selected) {
const range = this.props.nodeInfoToRange(selected.data);
this.selectedDecorations = this.editor.deltaDecorations(
this.selectedDecorations,
[
{
range,
options: { className: "selected" },
},
]
);
this.editor.revealRange(
range,
monaco.editor.ScrollType.Smooth
);
} else {
this.selectedDecorations = this.editor.deltaDecorations(
this.selectedDecorations,
[]
);
}
console.log("_updateSelectedDecoration");
if (!this.editor) {
return;
}
const range = this.selected;
if (range) {
this.selectedDecorations = this.editor.deltaDecorations(
this.selectedDecorations,
[
{
range,
options: { className: "selected" },
},
]
);
this.editor.revealRange(range, monaco.editor.ScrollType.Smooth);
} else {
this.selectedDecorations = this.editor.deltaDecorations(
this.selectedDecorations,
[]
);
}
},
{ name: "updateDecorations" }
);
private test = (() => {
console.log("test created");
})();
@computed.struct
private get modelData(): { text: string; languageId: string } {
const { text, languageId } = this.props;
return { text, languageId };
}
@disposeOnUnmount
private _updateText = autorun(() => {
if (this.editor) {
const model = monaco.editor.createModel(
this.props.text,
this.props.languageId,
undefined
);
private _updateText = autorun(
() => {
console.log("_updateText rerun");
if (this.editor) {
const model = monaco.editor.createModel(
this.modelData.text,
this.modelData.languageId,
undefined
);
this.editor.setModel(model);
this.editor.setModel(model);
if (this.modelNotObservable) {
this.modelNotObservable.dispose();
if (this.modelNotObservable) {
this.modelNotObservable.dispose();
}
this.modelNotObservable = model;
this.model = model;
}
this.model = model;
}
});
},
{ name: "Update Model" }
);
private readonly setEditorDiv = (editorDiv: HTMLDivElement) => {
if (!editorDiv) {

View File

@@ -19,7 +19,8 @@
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-measure": "^2.3.0",
"@hediet/debug-visualizer-data-extraction": "*"
"@hediet/debug-visualizer-data-extraction": "*",
"@knuddels/mobx-logger": "^1.1.1"
},
"devDependencies": {
"@types/html-webpack-plugin": "^3.2.2",

View File

@@ -103,19 +103,20 @@ export class VisualizerHeaderMain extends React.Component<{ model: Model }> {
<ExpressionInput model={m} />
</div>
<div style={{ width: 4 }} />
{m.loading ? (
<div style={{ padding: "0 4px" }}>
<Spinner size={Spinner.SIZE_SMALL} />
</div>
) : (
<Button
minimal
small
className="part-Icon"
icon="refresh"
onClick={() => m.refresh()}
/>
)}
{!m.isPolling &&
(m.loading ? (
<div style={{ padding: "0 4px" }}>
<Spinner size={Spinner.SIZE_SMALL} />
</div>
) : (
<Button
minimal
small
className="part-Icon"
icon="refresh"
onClick={() => m.refresh()}
/>
))}
<Button
minimal
small

View File

@@ -1,5 +1,5 @@
import * as React from "react";
import { Popover } from "@blueprintjs/core";
import { Popover, Checkbox } from "@blueprintjs/core";
import { DataExtractorInfo } from "@hediet/debug-visualizer-data-extraction";
import { computed } from "mobx";
import { observer } from "mobx-react";
@@ -80,6 +80,12 @@ export class VisualizerHeaderDetails extends React.Component<{ model: Model }> {
: []
}
/>
<div style={{ width: 10 }} />
<Checkbox
label="Poll"
checked={m.isPolling}
onChange={e => m.setPolling(e.currentTarget.checked)}
/>
</div>
);
}

View File

@@ -3,6 +3,7 @@ import * as ReactDOM from "react-dom";
import "./style.scss";
import { Model } from "./model/Model";
import Components = require("./components/GUI");
import * as mobx from "mobx";
const model = new Model();

View File

@@ -17,7 +17,7 @@ import {
import { getApi as getVsCodeApi } from "./VsCodeApi";
import { MonacoBridge } from "./MonacoBridge";
import { Disposable } from "@hediet/std/disposable";
import { startInterval } from "@hediet/std/timer";
import { startInterval, EventTimer } from "@hediet/std/timer";
declare const window: Window & {
webViewData?: {
@@ -55,6 +55,11 @@ export class Model {
| VisualizationId
| undefined = undefined;
@observable isPolling = false;
private readonly pollingTimer = this.dispose.track(
new EventTimer(500, "stopped")
);
@action
public setPreferredVisualizationId(id: VisualizationId) {
this.preferredVisualizationId = id;
@@ -65,6 +70,16 @@ export class Model {
this.state = { kind: "visualizationError", data: data };
}
@action
public setPolling(value: boolean) {
this.isPolling = value;
if (value) {
this.pollingTimer.start();
} else {
this.pollingTimer.stop();
}
}
@computed get visualizations():
| {
visualization: Visualization | undefined;
@@ -163,6 +178,10 @@ export class Model {
this.setExpression(state.expression);
}
});
this.pollingTimer.onTick.sub(() => {
this.refresh();
});
}
@action

View File

@@ -32,6 +32,14 @@ module.exports = {
path: r("dist"),
filename: "[name].js",
chunkFilename: "[name]-[hash].js",
devtoolModuleFilenameTemplate: info => {
let result = info.absoluteResourcePath.replace(/\\/g, "/");
if (!result.startsWith("file:")) {
// Some paths already start with the file scheme.
result = "file:///" + result;
}
return result;
},
},
resolve: {
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"],

View File

@@ -320,6 +320,11 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@knuddels/mobx-logger@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@knuddels/mobx-logger/-/mobx-logger-1.1.1.tgz#64f3d449d5fabfdd710616d668a6d898cc9caa7f"
integrity sha512-5iVhsa8e4Gsfg/UbgKGSLOMcZdcjl5usZmpVm50mK/CQgnsjupE6KNS/514VnWcwaW3w38Rv0uherHYhEInDuQ==
"@mapbox/geojson-area@0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz#18d7814aa36bf23fbbcc379f8e26a22927debf10"