Skip to content

Commit 548d095

Browse files
committed
Add support for running extensions in the browser
1 parent 846dcbb commit 548d095

24 files changed

+727
-51
lines changed

main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
// while still allowing us to access files within the binary.
55
process.env.NBIN_BYPASS = true;
66

7-
require("../../bootstrap-amd").load("vs/server/src/cli");
7+
require("../../bootstrap-amd").load("vs/server/src/node/cli");

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@
2727
},
2828
"dependencies": {
2929
"@coder/logger": "^1.1.8",
30+
"@coder/node-browser": "^1.0.0",
31+
"@coder/requirefs": "^1.0.3",
3032
"httpolyglot": "^0.1.2",
3133
"pem": "^1.14.2",
3234
"safe-compare": "^1.1.4",
3335
"tar-fs": "^2.0.0",
34-
"tar-stream": "^2.1.0"
36+
"tar-stream": "^2.1.0",
37+
"util": "^0.12.1"
3538
}
3639
}

scripts/build-json.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ const writeProduct = () => {
4545
"vs/workbench/workbench.web.api.css",
4646
"vs/code/browser/workbench/workbench.html",
4747
"vs/code/browser/workbench/workbench.js",
48-
"vs/server/src/cli.js",
49-
"vs/server/src/uriTransformer.js",
48+
"vs/server/src/node/cli.js",
49+
"vs/server/src/node/uriTransformer.js",
5050
"vs/server/src/login/index.html"
5151
]);
5252
const date = new Date().toISOString();

scripts/vscode.patch

Lines changed: 337 additions & 11 deletions
Large diffs are not rendered by default.

src/api.ts renamed to src/browser/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vscode from "vscode";
2-
import { CoderApi, VSCodeApi } from "../typings/api";
2+
import { CoderApi, VSCodeApi } from "../../typings/api";
33
import { createCSSRule } from "vs/base/browser/dom";
44
import { Emitter, Event } from "vs/base/common/event";
55
import { IDisposable } from "vs/base/common/lifecycle";

src/client.ts renamed to src/browser/client.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
import { Emitter } from "vs/base/common/event";
12
import { URI } from "vs/base/common/uri";
23
import { registerSingleton } from "vs/platform/instantiation/common/extensions";
34
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
4-
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
55
import { ILocalizationsService } from "vs/platform/localizations/common/localizations";
66
import { LocalizationsService } from "vs/platform/localizations/electron-browser/localizationsService";
7+
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
78
import { IUpdateService } from "vs/platform/update/common/update";
89
import { UpdateService } from "vs/platform/update/electron-browser/updateService";
9-
import { TelemetryChannelClient } from "vs/server/src/telemetry";
10-
import { IUploadService, UploadService } from 'vs/server/src/upload';
10+
import { coderApi, vscodeApi } from "vs/server/src/browser/api";
11+
import { IUploadService, UploadService } from "vs/server/src/browser/upload";
12+
import { INodeProxyService, NodeProxyChannelClient } from "vs/server/src/common/nodeProxy";
13+
import { TelemetryChannelClient } from "vs/server/src/common/telemetry";
14+
import "vs/workbench/contrib/localizations/browser/localizations.contribution";
15+
import "vs/workbench/contrib/update/electron-browser/update.contribution";
1116
import { IRemoteAgentService } from "vs/workbench/services/remote/common/remoteAgentService";
1217

1318
class TelemetryService extends TelemetryChannelClient {
@@ -18,16 +23,28 @@ class TelemetryService extends TelemetryChannelClient {
1823
}
1924
}
2025

26+
class NodeProxyService extends NodeProxyChannelClient implements INodeProxyService {
27+
private readonly _onClose = new Emitter<void>();
28+
public readonly onClose = this._onClose.event;
29+
private readonly _onDown = new Emitter<void>();
30+
public readonly onDown = this._onDown.event;
31+
private readonly _onUp = new Emitter<void>();
32+
public readonly onUp = this._onUp.event;
33+
34+
public constructor(
35+
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
36+
) {
37+
// TODO: up/down/close
38+
super(remoteAgentService.getConnection()!.getChannel("nodeProxy"));
39+
}
40+
}
41+
2142
registerSingleton(ILocalizationsService, LocalizationsService);
43+
registerSingleton(INodeProxyService, NodeProxyService);
2244
registerSingleton(ITelemetryService, TelemetryService);
2345
registerSingleton(IUpdateService, UpdateService);
2446
registerSingleton(IUploadService, UploadService, true);
2547

26-
import "vs/workbench/contrib/update/electron-browser/update.contribution";
27-
import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
28-
29-
import { coderApi, vscodeApi } from "vs/server/src/api";
30-
3148
/**
3249
* This is called by vs/workbench/browser/web.main.ts after the workbench has
3350
* been initialized so we can initialize our own client-side code.

src/browser/extHostNodeProxy.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Emitter } from "vs/base/common/event";
2+
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
3+
import { ExtHostNodeProxyShape, MainContext, MainThreadNodeProxyShape } from "vs/workbench/api/common/extHost.protocol";
4+
import { IExtHostRpcService } from "vs/workbench/api/common/extHostRpcService";
5+
6+
export class ExtHostNodeProxy implements ExtHostNodeProxyShape {
7+
_serviceBrand: any;
8+
9+
private readonly _onMessage = new Emitter<string>();
10+
public readonly onMessage = this._onMessage.event;
11+
private readonly _onClose = new Emitter<void>();
12+
public readonly onClose = this._onClose.event;
13+
private readonly _onDown = new Emitter<void>();
14+
public readonly onDown = this._onDown.event;
15+
private readonly _onUp = new Emitter<void>();
16+
public readonly onUp = this._onUp.event;
17+
18+
private readonly proxy: MainThreadNodeProxyShape;
19+
20+
constructor(@IExtHostRpcService rpc: IExtHostRpcService) {
21+
this.proxy = rpc.getProxy(MainContext.MainThreadNodeProxy);
22+
}
23+
24+
public $onMessage(message: string): void {
25+
this._onMessage.fire(message);
26+
}
27+
28+
public $onClose(): void {
29+
this._onClose.fire();
30+
}
31+
32+
public $onUp(): void {
33+
this._onUp.fire();
34+
}
35+
36+
public $onDown(): void {
37+
this._onDown.fire();
38+
}
39+
40+
public send(message: string): void {
41+
this.proxy.$send(message);
42+
}
43+
}
44+
45+
export interface IExtHostNodeProxy extends ExtHostNodeProxy { }
46+
export const IExtHostNodeProxy = createDecorator<IExtHostNodeProxy>('IExtHostNodeProxy');

src/browser/mainThreadNodeProxy.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { IDisposable } from "vs/base/common/lifecycle";
2+
import { INodeProxyService } from "vs/server/src/common/nodeProxy";
3+
import { ExtHostContext, IExtHostContext, MainContext, MainThreadNodeProxyShape } from "vs/workbench/api/common/extHost.protocol";
4+
import { extHostNamedCustomer } from "vs/workbench/api/common/extHostCustomers";
5+
6+
@extHostNamedCustomer(MainContext.MainThreadNodeProxy)
7+
export class MainThreadNodeProxy implements MainThreadNodeProxyShape {
8+
private disposed = false;
9+
private disposables = <IDisposable[]>[];
10+
11+
constructor(
12+
extHostContext: IExtHostContext,
13+
@INodeProxyService private readonly proxyService: INodeProxyService,
14+
) {
15+
if (!extHostContext.remoteAuthority) { // HACK: A terrible way to detect if running in the worker.
16+
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostNodeProxy);
17+
this.disposables = [
18+
this.proxyService.onMessage((message: string) => proxy.$onMessage(message)),
19+
this.proxyService.onClose(() => proxy.$onClose()),
20+
this.proxyService.onDown(() => proxy.$onDown()),
21+
this.proxyService.onUp(() => proxy.$onUp()),
22+
];
23+
}
24+
}
25+
26+
$send(message: string): void {
27+
if (!this.disposed) {
28+
this.proxyService.send(message);
29+
}
30+
}
31+
32+
dispose(): void {
33+
this.disposables.forEach((d) => d.dispose());
34+
this.disposables = [];
35+
this.disposed = true;
36+
}
37+
}
File renamed without changes.

src/common/nodeProxy.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Event } from "vs/base/common/event";
2+
import { IChannel, IServerChannel } from "vs/base/parts/ipc/common/ipc";
3+
import { createDecorator } from "vs/platform/instantiation/common/instantiation";
4+
import { ReadWriteConnection } from "vs/server/node_modules/@coder/node-browser/out/common/connection";
5+
6+
export const INodeProxyService = createDecorator<INodeProxyService>("nodeProxyService");
7+
8+
export interface INodeProxyService extends ReadWriteConnection {
9+
_serviceBrand: any;
10+
send(message: string): void;
11+
onMessage: Event<string>;
12+
onUp: Event<void>;
13+
onClose: Event<void>;
14+
onDown: Event<void>;
15+
}
16+
17+
export class NodeProxyChannel implements IServerChannel {
18+
constructor(private service: INodeProxyService) {}
19+
20+
listen(_: unknown, event: string): Event<any> {
21+
switch (event) {
22+
case "onMessage": return this.service.onMessage;
23+
}
24+
throw new Error(`Invalid listen ${event}`);
25+
}
26+
27+
async call(_: unknown, command: string, args?: any): Promise<any> {
28+
switch (command) {
29+
case "send": return this.service.send(args[0]);
30+
}
31+
throw new Error(`Invalid call ${command}`);
32+
}
33+
}
34+
35+
export class NodeProxyChannelClient {
36+
_serviceBrand: any;
37+
38+
public readonly onMessage: Event<string>;
39+
40+
constructor(private readonly channel: IChannel) {
41+
this.onMessage = this.channel.listen<string>("onMessage");
42+
}
43+
44+
public send(data: string): void {
45+
this.channel.call("send", [data]);
46+
}
47+
}

0 commit comments

Comments
 (0)