Skip to content

Commit 9f57eab

Browse files
committed
allow to work in virtual workspaces and web
Fixes #36
1 parent 581e38b commit 9f57eab

File tree

17 files changed

+80
-190
lines changed

17 files changed

+80
-190
lines changed

.ci/release.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ jobs:
2626
- script: npm run compile
2727
displayName: 'npm run compile'
2828

29-
- script: vsce publish --yarn --noVerify -p $(vsce.token)
29+
- script: vsce publish --yarn --noVerify --web -p $(vsce.token)
3030
displayName: 'flame: vsce publish'
3131
workingDirectory: packages/vscode-js-profile-flame
3232

33-
- script: vsce publish --yarn --noVerify -p $(vsce.token)
33+
- script: vsce publish --yarn --noVerify --web -p $(vsce.token)
3434
displayName: 'table: vsce publish'
3535
workingDirectory: packages/vscode-js-profile-table

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ A custom editor for viewing `.cpuprofile` files in VS Code. Pairs well with out
1111
This is a Lerna monorepo, with a core package that shares data models and some UI between extensions.
1212

1313
- You can use `npm run watch` to watch _everything_, or, for example, `npm run watch:flame`, to only watch changes to the flame graph extension.
14-
- Extensions can be viewed as standalone pages in the browser for rapid development via `npm run standalone:flame`
1514
- There's a launch config that runs all extensions.
1615
- `npm run compile`, again with scopes like `compile:flame`, create static compilations of various packages.
1716
- If you need to install a dependency in one package, you can use `lerna add`, or add it to the package.json and then run `lerna bootstrap`.

package.json

+8-28
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,15 @@
44
"scripts": {
55
"postinstall": "lerna bootstrap --force-local",
66
"clean": "rimraf \"packages/*/out\"",
7-
"compile": "npm run clean && concurrently \"npm:compile:core:*\" && concurrently \"npm:compile:table\" \"npm:compile:flame\"",
8-
"compile:core": "concurrently \"npm:compile:core:*\"",
9-
"compile:core:ext": "cd packages/vscode-js-profile-core && tsc -p tsconfig.json",
10-
"compile:core:esm": "cd packages/vscode-js-profile-core && tsc -p tsconfig.browser.json",
11-
"compile:core:css": "cd packages/vscode-js-profile-core && cpy --parents --cwd=src \"**/*.css\" ../out/esm",
12-
"compile:table": "concurrently \"npm:compile:table:*\" && rimraf packages/vscode-js-profile-table/out/client",
13-
"compile:table:ext": "cd packages/vscode-js-profile-table && webpack --config webpack.extension.js",
14-
"compile:table:webpack": "cd packages/vscode-js-profile-table && webpack --mode production --config webpack.client.js",
15-
"compile:flame": "concurrently \"npm:compile:flame:*\" && rimraf packages/vscode-js-profile-flame/out/client",
16-
"compile:flame:ext": "cd packages/vscode-js-profile-flame && webpack --config webpack.extension.js",
17-
"compile:flame:webpack": "cd packages/vscode-js-profile-flame && webpack --mode production --config webpack.client.js",
18-
"compile:flame:realtime": "cd packages/vscode-js-profile-flame && webpack --mode production --config webpack.realtime.js",
7+
"compile": "npm run clean && npm run compile:core && concurrently \"npm:compile:table\" \"npm:compile:flame\"",
8+
"compile:core": "lerna run --scope vscode-js-profile-core compile",
9+
"compile:table": "lerna run --scope vscode-js-profile-table compile",
10+
"compile:flame": "lerna run --scope vscode-js-profile-flame compile",
1911
"watch": "concurrently \"npm:watch:core:*\" \"npm:watch:flame:*\" \"npm:watch:table:*\"",
20-
"watch:core:ext": "cd packages/vscode-js-profile-core && tsc --watch",
21-
"watch:core:esm": "cd packages/vscode-js-profile-core && tsc --watch -p tsconfig.browser.json",
22-
"watch:core:css": "npm run compile:core:css && cd packages/vscode-js-profile-core && chokidar \"src/**/*.css\" -c \"cpy --parents --cwd=src '**/*.css' ../out/esm\"",
23-
"watch:table": "concurrently \"npm:watch:table:*\" \"npm:watch:core:*\"",
24-
"watch:table:ext": "cd packages/vscode-js-profile-table && webpack --config webpack.extension.js --watch",
25-
"watch:table:webpack": "cd packages/vscode-js-profile-table && webpack --config webpack.client.js --watch",
26-
"watch:flame": "concurrently \"npm:watch:flame:*\" \"npm:watch:core:*\"",
27-
"watch:flame-only": "concurrently \"npm:watch:flame:*\"",
28-
"watch:flame:ext": "cd packages/vscode-js-profile-flame && webpack --config webpack.extension.js --watch",
29-
"watch:flame:webpack": "cd packages/vscode-js-profile-flame && webpack --config webpack.client.js --watch",
30-
"watch:flame:realtime": "cd packages/vscode-js-profile-flame && webpack --config webpack.realtime.js --watch",
31-
"watch:notebook": "concurrently \"npm:watch:notebook:*\" \"npm:watch:core:*\"",
32-
"watch:notebook:ext": "cd packages/vscode-js-profile-notebook && webpack --config webpack.extension.js --watch",
33-
"watch:notebook:webpack": "cd packages/vscode-js-profile-notebook && webpack-dev-server --config webpack.client.js --hot",
34-
"standalone:flame": "cd packages/vscode-js-profile-flame && cross-env STANDALONE=1 VIZ_MODEL=../../samples/cpu-model.json webpack-dev-server",
35-
"standalone:table": "cd packages/vscode-js-profile-table && cross-env STANDALONE=1 VIZ_MODEL=../../samples/cpu-model.json webpack-dev-server",
12+
"watch:core": "lerna run --scope vscode-js-profile-core watch",
13+
"watch:table": "lerna run --scope vscode-js-profile-table watch",
14+
"watch:flame": "lerna run --scope vscode-js-profile-flame watch",
15+
"pack": "npm run compile && lerna run pack",
3616
"fmt": "prettier --write \"packages/**/*.{ts,tsx,css}\" \"!**/out/**\" && npm run test:lint -- --fix",
3717
"test": "concurrently \"npm:test:*\"",
3818
"test:lint": "eslint \"packages/**/*.{ts,tsx}\"",

packages/vscode-js-profile-core/package.json

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
"version": "0.0.18",
44
"sideEffects": false,
55
"private": true,
6+
"scripts": {
7+
"compile": "concurrently \"npm:compile:*\"",
8+
"compile:ext": "tsc -p tsconfig.json",
9+
"compile:esm": "tsc -p tsconfig.browser.json",
10+
"compile:css": "cpy --parents --cwd=src \"**/*.css\" ../out/esm",
11+
"watch": "concurrently \"npm:watch:*\"",
12+
"watch:ext": "tsc --watch",
13+
"watch:esm": "tsc --watch -p tsconfig.browser.json",
14+
"watch:css": "npm run compile:css && cd packages/vscode-js-profile-core && chokidar \"src/**/*.css\" -c \"cpy --parents --cwd=src '**/*.css' ../out/esm\""
15+
},
616
"dependencies": {
717
"node-fetch": "^2.6.1",
818
"vscode-codicons": "github:microsoft/vscode-codicons#dd1edb245d2217efcfb931c293b77b78e634e59a"

packages/vscode-js-profile-core/src/bundlePage.ts

+10-14
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,24 @@
22
* Copyright (C) Microsoft Corporation. All rights reserved.
33
*--------------------------------------------------------*/
44

5-
import { promises as fs } from 'fs';
6-
import { randomBytes } from 'crypto';
7-
8-
export const bundlePage = async (bundleFile: string, constants: { [key: string]: unknown }) => {
9-
const bundle = await fs.readFile(bundleFile, 'utf-8');
10-
const nonce = randomBytes(16).toString('hex');
11-
const constantDecls = Object.keys(constants)
12-
.map(key => `const ${key} = ${JSON.stringify(constants[key])};`)
13-
.join('\n');
5+
import * as vscode from 'vscode';
146

7+
export const bundlePage = async (bundleUri: vscode.Uri, constants: { [key: string]: unknown }) => {
8+
const nonce = Math.random().toString();
159
const html = `<!DOCTYPE html>
1610
<html lang="en">
1711
<head>
1812
<meta charset="UTF-8">
1913
<meta name="viewport" content="width=device-width, initial-scale=1.0">
20-
<title>Custom Editor: ${bundleFile}</title>
14+
<title>Profile Custom Editor</title>
2115
</head>
2216
<body>
23-
<script type="text/javascript" nonce="${nonce}">(() => {
24-
${constantDecls}
25-
${bundle}
26-
})();</script>
17+
<script type="text/javascript" nonce="${nonce}">
18+
${Object.entries(constants)
19+
.map(([key, value]) => `globalThis.${key} = ${JSON.stringify(value)}`)
20+
.join(';')}
21+
</script>
22+
<script nonce="${nonce}" src="${bundleUri}"></script>
2723
</body>
2824
</html>
2925
`;

packages/vscode-js-profile-core/src/cpu/editorProvider.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class CpuProfileEditorProvider
1818

1919
constructor(
2020
private readonly lens: ProfileCodeLensProvider,
21-
private readonly bundle: string,
21+
private readonly bundle: vscode.Uri,
2222
private readonly extraConsts: Record<string, unknown> = {},
2323
) {}
2424

@@ -27,7 +27,7 @@ export class CpuProfileEditorProvider
2727
*/
2828
async openCustomDocument(uri: vscode.Uri) {
2929
const content = await vscode.workspace.fs.readFile(uri);
30-
const raw: ICpuProfileRaw = JSON.parse(content.toString());
30+
const raw: ICpuProfileRaw = JSON.parse(new TextDecoder().decode(content));
3131
const document = new ReadonlyCustomDocument(uri, buildModel(raw));
3232

3333
const annotations = new ProfileAnnotations();
@@ -66,7 +66,7 @@ export class CpuProfileEditorProvider
6666
});
6767

6868
webviewPanel.webview.options = { enableScripts: true };
69-
webviewPanel.webview.html = await bundlePage(this.bundle, {
69+
webviewPanel.webview.html = await bundlePage(webviewPanel.webview.asWebviewUri(this.bundle), {
7070
MODEL: document.userData,
7171
...this.extraConsts,
7272
});

packages/vscode-js-profile-core/src/path.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
*--------------------------------------------------------*/
44

55
import * as path from 'path';
6-
import { promises as fs } from 'fs';
6+
import * as vscode from 'vscode';
77

88
export const exists = async (file: string) => {
99
try {
10-
await fs.stat(file);
10+
await vscode.workspace.fs.stat(vscode.Uri.file(file));
1111
return true;
1212
} catch {
1313
return false;
@@ -18,9 +18,10 @@ export const exists = async (file: string) => {
1818
* Resolves path segments properly based on whether they appear to be c:/ -style or / style.
1919
*/
2020
export function properRelative(fromPath: string, toPath: string): string {
21-
if (path.posix.isAbsolute(fromPath)) {
21+
// note: posix and win32 are not available in the browser polyfill.
22+
if (path.posix?.isAbsolute(fromPath)) {
2223
return path.posix.relative(fromPath, toPath);
23-
} else if (path.win32.isAbsolute(fromPath)) {
24+
} else if (path.win32?.isAbsolute(fromPath)) {
2425
return path.win32.relative(fromPath, toPath);
2526
} else {
2627
return path.relative(fromPath, toPath);

packages/vscode-js-profile-flame/package.json

+18-2
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,38 @@
66
"homepage": "https://github.com/microsoft/vscode-js-profile-visualizer#readme",
77
"license": "MIT",
88
"main": "out/extension.js",
9+
"browser": "out/extension.web.js",
910
"files": [
1011
"out"
1112
],
1213
"repository": {
1314
"type": "git",
1415
"url": "https://github.com/microsoft/vscode-js-profile-visualizer.git"
1516
},
16-
"workspaceTrust": {
17-
"request": "never"
17+
"capabilities": {
18+
"virtualWorkspaces": true,
19+
"untrustedWorkspaces": {
20+
"supported": true
21+
}
1822
},
1923
"publisher": "ms-vscode",
2024
"enableProposedApi": true,
2125
"sideEffects": false,
2226
"engines": {
2327
"vscode": "^1.50.0-insider"
2428
},
29+
"scripts": {
30+
"pack": "vsce package --yarn",
31+
"compile": "rimraf out && concurrently \"npm:compile:*\"",
32+
"compile:client": "webpack --mode production --config webpack.client.js",
33+
"compile:realtime": "webpack --mode production --config webpack.realtime.js",
34+
"compile:ext": "webpack --mode production --config webpack.extension.js --target node",
35+
"compile:ext:web": "webpack --mode production --config webpack.extension.js --target web",
36+
"watch": "concurrent \"npm:watch:*\"",
37+
"watch:client": "webpack --mode development --config webpack.client.js --watch",
38+
"watch:realtime": "webpack --mode development --config webpack.realtime.js --watch",
39+
"watch:ext": "webpack --mode development --config webpack.extension.js --watch"
40+
},
2541
"icon": "resources/logo.png",
2642
"activationEvents": [
2743
"onView:vscode-js-profile-flame.realtime",

packages/vscode-js-profile-flame/src/extension.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const enum Config {
1010

1111
const allConfig = [Config.PollInterval, Config.ViewDuration, Config.Easing];
1212

13-
import { join } from 'path';
1413
import * as vscode from 'vscode';
1514
import { CpuProfileEditorProvider } from 'vscode-js-profile-core/out/cpu/editorProvider';
1615
import { ProfileCodeLensProvider } from 'vscode-js-profile-core/out/profileCodeLensProvider';
@@ -27,7 +26,7 @@ export function activate(context: vscode.ExtensionContext) {
2726
'jsProfileVisualizer.cpuprofile.flame',
2827
new CpuProfileEditorProvider(
2928
new ProfileCodeLensProvider(),
30-
join(__dirname, 'client.bundle.js'),
29+
vscode.Uri.joinPath(context.extensionUri, 'out', 'client.bundle.js'),
3130
),
3231
),
3332

packages/vscode-js-profile-flame/src/realtimeWebviewProvider.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Copyright (C) Microsoft Corporation. All rights reserved.
33
*--------------------------------------------------------*/
44

5-
import { randomBytes } from 'crypto';
65
import * as vscode from 'vscode';
76
import { FromWebViewMessage, MessageType } from './realtime/protocol';
87
import { RealtimeSessionTracker } from './realtimeSessionTracker';
@@ -41,7 +40,7 @@ export class RealtimeWebviewProvider implements vscode.WebviewViewProvider {
4140
const scriptUri = webview.asWebviewUri(
4241
vscode.Uri.joinPath(this.extensionUri, 'out', 'realtime.bundle.js'),
4342
);
44-
const nonce = randomBytes(16).toString('hex');
43+
const nonce = Math.random().toString();
4544

4645
return `<!DOCTYPE html>
4746
<html lang="en">

packages/vscode-js-profile-notebook/src/notebook-provider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class NotebookProvider implements vscode.NotebookProvider {
4242
*/
4343
public async resolveNotebook(editor: vscode.NotebookEditor): Promise<void> {
4444
const content = await vscode.workspace.fs.readFile(editor.document.uri);
45-
const raw: ICpuProfileWithNotebook = JSON.parse(content.toString());
45+
const raw: ICpuProfileWithNotebook = JSON.parse(new TextDecoder().decode(content));
4646
const model = buildModel(raw);
4747
this.models.set(editor.document, { raw, model, bottomUp: createBottomUpGraph(model) });
4848
editor.document.languages = ['cpuprofile'];

packages/vscode-js-profile-table/package.json

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"homepage": "https://github.com/microsoft/vscode-js-profile-visualizer#readme",
77
"license": "MIT",
88
"main": "out/extension.js",
9+
"browser": "out/extension.web.js",
910
"files": [
1011
"out"
1112
],
@@ -14,11 +15,21 @@
1415
"url": "https://github.com/microsoft/vscode-js-profile-visualizer.git"
1516
},
1617
"capabilities": {
17-
"virtualWorkspaces": false,
18+
"virtualWorkspaces": true,
1819
"untrustedWorkspaces": {
1920
"supported": true
2021
}
2122
},
23+
"scripts": {
24+
"pack": "vsce package --yarn",
25+
"compile": "rimraf out && concurrently \"npm:compile:*\"",
26+
"compile:client": "webpack --mode production --config webpack.client.js",
27+
"compile:ext": "webpack --mode production --config webpack.extension.js --target node",
28+
"compile:ext:web": "webpack --mode production --config webpack.extension.js --target web",
29+
"watch": "concurrent \"npm:watch:*\"",
30+
"watch:client": "webpack --mode development --config webpack.client.js --watch",
31+
"watch:ext": "webpack --mode development --config webpack.extension.js --watch"
32+
},
2233
"icon": "resources/icon.png",
2334
"publisher": "ms-vscode",
2435
"enableProposedApi": true,

packages/vscode-js-profile-table/src/extension.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44

55
import * as vscode from 'vscode';
66
import { CpuProfileEditorProvider } from 'vscode-js-profile-core/out/cpu/editorProvider';
7-
import { ProfileCodeLensProvider } from 'vscode-js-profile-core/out/profileCodeLensProvider';
87
import { DownloadFileProvider } from 'vscode-js-profile-core/out/download-file-provider';
9-
import { join } from 'path';
8+
import { ProfileCodeLensProvider } from 'vscode-js-profile-core/out/profileCodeLensProvider';
109

1110
export function activate(context: vscode.ExtensionContext) {
1211
const lenses = new ProfileCodeLensProvider();
1312

1413
context.subscriptions.push(
1514
vscode.window.registerCustomEditorProvider(
1615
'jsProfileVisualizer.cpuprofile.table',
17-
new CpuProfileEditorProvider(lenses, join(__dirname, 'client.bundle.js')),
16+
new CpuProfileEditorProvider(
17+
lenses,
18+
vscode.Uri.joinPath(context.extensionUri, 'out', 'client.bundle.js'),
19+
),
1820
),
1921
vscode.workspace.registerTextDocumentContentProvider(
2022
'js-viz-download',

samples/index.ejs

-95
This file was deleted.

scripts/tsconfig.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"compilerOptions": {
33
"module": "commonjs",
4-
"target": "es6",
4+
"target": "ES2019",
55
"outDir": "out",
66
"lib": [
7-
"es6",
7+
"ES2019",
88
"dom"
99
],
1010
"declaration": false,

scripts/webpack.client.js

-27
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,6 @@
11
const path = require('path');
2-
const fs = require('fs');
3-
const { join } = require('path');
4-
const HtmlWebpackPlugin = require('html-webpack-plugin');
5-
6-
const standalone = process.env.STANDALONE === '1';
72
const production = process.argv.includes('production');
83

9-
const constants = {};
10-
if (standalone) {
11-
const constantPrefix = 'VIZ_';
12-
for (const key of Object.keys(process.env).filter(k => k.startsWith(constantPrefix))) {
13-
const value = process.env[key];
14-
const name = key.slice(constantPrefix.length);
15-
try {
16-
constants[name] = JSON.parse(fs.readFileSync(value, 'utf-8'));
17-
} catch {
18-
constants[name] = JSON.parse(value);
19-
}
20-
}
21-
}
22-
234
module.exports = (dirname, file = 'client') => ({
245
mode: production ? 'production' : 'development',
256
devtool: production ? false : 'inline-source-map',
@@ -70,12 +51,4 @@ module.exports = (dirname, file = 'client') => ({
7051
'Access-Control-Allow-Origin': '*',
7152
},
7253
},
73-
plugins: standalone
74-
? [
75-
new HtmlWebpackPlugin({
76-
template: join(__dirname, '..', 'samples/index.ejs'),
77-
templateParameters: { constants },
78-
}),
79-
]
80-
: [],
8154
});

scripts/webpack.extension.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ const production = process.argv.includes('production');
33

44
module.exports = dirname => ({
55
mode: production ? 'production' : 'development',
6-
target: 'node',
76
devtool: production ? false : 'source-map',
87
entry: './src/extension.ts',
98
output: {
109
path: path.join(dirname, 'out'),
11-
filename: 'extension.js',
12-
libraryTarget: 'commonjs2'
10+
filename: process.argv.includes('web') ? 'extension.web.js' : 'extension.js',
11+
libraryTarget: 'commonjs2',
1312
},
1413
resolve: {
1514
extensions: ['.ts', '.js', '.json'],

0 commit comments

Comments
 (0)