Hook up shared process sorta
This commit is contained in:
parent
d827015b40
commit
811260cc80
|
@ -1,5 +1,6 @@
|
||||||
|
import { Event } from "@coder/events";
|
||||||
import { field, logger, time, Time } from "@coder/logger";
|
import { field, logger, time, Time } from "@coder/logger";
|
||||||
import { InitData } from "@coder/protocol";
|
import { InitData, ISharedProcessData } from "@coder/protocol";
|
||||||
import { retry, Retry } from "./retry";
|
import { retry, Retry } from "./retry";
|
||||||
import { client } from "./fill/client";
|
import { client } from "./fill/client";
|
||||||
import { Clipboard, clipboard } from "./fill/clipboard";
|
import { Clipboard, clipboard } from "./fill/clipboard";
|
||||||
|
@ -167,6 +168,10 @@ export abstract class Client {
|
||||||
return client.initData;
|
return client.initData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get onSharedProcessActive(): Event<ISharedProcessData> {
|
||||||
|
return client.onSharedProcessActive;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the IDE.
|
* Initialize the IDE.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
import { Net } from "@coder/protocol";
|
import { Net } from "@coder/protocol";
|
||||||
|
import { client } from "./client";
|
||||||
|
|
||||||
export = new Net();
|
export = new Net(client);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ReadWriteConnection, InitData, OperatingSystem } from "../common/connection";
|
import { ReadWriteConnection, InitData, OperatingSystem, ISharedProcessData } from "../common/connection";
|
||||||
import { NewEvalMessage, ServerMessage, EvalDoneMessage, EvalFailedMessage, TypedValue, ClientMessage, NewSessionMessage, TTYDimensions, SessionOutputMessage, CloseSessionInputMessage, WorkingInitMessage, NewConnectionMessage } from "../proto";
|
import { NewEvalMessage, ServerMessage, EvalDoneMessage, EvalFailedMessage, TypedValue, ClientMessage, NewSessionMessage, TTYDimensions, SessionOutputMessage, CloseSessionInputMessage, WorkingInitMessage, NewConnectionMessage } from "../proto";
|
||||||
import { Emitter } from "@coder/events";
|
import { Emitter, Event } from "@coder/events";
|
||||||
import { logger, field } from "@coder/logger";
|
import { logger, field } from "@coder/logger";
|
||||||
import { ChildProcess, SpawnOptions, ServerProcess, ServerSocket, Socket } from "./command";
|
import { ChildProcess, SpawnOptions, ServerProcess, ServerSocket, Socket } from "./command";
|
||||||
|
|
||||||
|
@ -19,17 +19,17 @@ export class Client {
|
||||||
private readonly connections: Map<number, ServerSocket> = new Map();
|
private readonly connections: Map<number, ServerSocket> = new Map();
|
||||||
|
|
||||||
private _initData: InitData | undefined;
|
private _initData: InitData | undefined;
|
||||||
private initDataEmitter: Emitter<InitData> = new Emitter();
|
private initDataEmitter = new Emitter<InitData>();
|
||||||
private initDataPromise: Promise<InitData>;
|
private initDataPromise: Promise<InitData>;
|
||||||
|
|
||||||
|
private sharedProcessActiveEmitter = new Emitter<ISharedProcessData>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param connection Established connection to the server
|
* @param connection Established connection to the server
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly connection: ReadWriteConnection,
|
private readonly connection: ReadWriteConnection,
|
||||||
) {
|
) {
|
||||||
this.initDataEmitter = new Emitter();
|
|
||||||
|
|
||||||
connection.onMessage((data) => {
|
connection.onMessage((data) => {
|
||||||
try {
|
try {
|
||||||
this.handleMessage(ServerMessage.deserializeBinary(data));
|
this.handleMessage(ServerMessage.deserializeBinary(data));
|
||||||
|
@ -47,6 +47,10 @@ export class Client {
|
||||||
return this.initDataPromise;
|
return this.initDataPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get onSharedProcessActive(): Event<ISharedProcessData> {
|
||||||
|
return this.sharedProcessActiveEmitter.event;
|
||||||
|
}
|
||||||
|
|
||||||
public evaluate<R>(func: () => R | Promise<R>): Promise<R>;
|
public evaluate<R>(func: () => R | Promise<R>): Promise<R>;
|
||||||
public evaluate<R, T1>(func: (a1: T1) => R | Promise<R>, a1: T1): Promise<R>;
|
public evaluate<R, T1>(func: (a1: T1) => R | Promise<R>, a1: T1): Promise<R>;
|
||||||
public evaluate<R, T1, T2>(func: (a1: T1, a2: T2) => R | Promise<R>, a1: T1, a2: T2): Promise<R>;
|
public evaluate<R, T1, T2>(func: (a1: T1, a2: T2) => R | Promise<R>, a1: T1, a2: T2): Promise<R>;
|
||||||
|
@ -315,6 +319,10 @@ export class Client {
|
||||||
}
|
}
|
||||||
c.emit("end");
|
c.emit("end");
|
||||||
this.connections.delete(message.getConnectionFailure()!.getId());
|
this.connections.delete(message.getConnectionFailure()!.getId());
|
||||||
|
} else if (message.hasSharedProcessActive()) {
|
||||||
|
this.sharedProcessActiveEmitter.emit({
|
||||||
|
socketPath: message.getSharedProcessActive()!.getSocketPath(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as net from "net";
|
import * as net from "net";
|
||||||
import { Client } from '../client';
|
import { Client } from "../client";
|
||||||
|
|
||||||
type NodeNet = typeof net;
|
type NodeNet = typeof net;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export class Net implements NodeNet {
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line no-any
|
||||||
public createConnection(...args: any[]): net.Socket {
|
public createConnection(...args: any[]): net.Socket {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
return this.client.createConnection(...args) as net.Socket;
|
return this.client.createConnection(...args) as net.Socket;
|
||||||
|
|
|
@ -20,4 +20,8 @@ export interface InitData {
|
||||||
readonly workingDirectory: string;
|
readonly workingDirectory: string;
|
||||||
readonly homeDirectory: string;
|
readonly homeDirectory: string;
|
||||||
readonly tmpDirectory: string;
|
readonly tmpDirectory: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISharedProcessData {
|
||||||
|
readonly socketPath: string;
|
||||||
|
}
|
||||||
|
|
|
@ -117,9 +117,11 @@ export class Entry extends Command {
|
||||||
app.wss.on("connection", (ws, req) => {
|
app.wss.on("connection", (ws, req) => {
|
||||||
const id = clientId++;
|
const id = clientId++;
|
||||||
|
|
||||||
if (sharedProcess.state === SharedProcessState.Ready) {
|
ws.on("open", () => {
|
||||||
sendSharedProcessReady(ws);
|
if (sharedProcess.state === SharedProcessState.Ready) {
|
||||||
}
|
sendSharedProcessReady(ws);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress));
|
logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress));
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,6 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
||||||
};
|
};
|
||||||
|
|
||||||
wss.on("connection", (ws: WebSocket, req) => {
|
wss.on("connection", (ws: WebSocket, req) => {
|
||||||
const spm = (<any>req).sharedProcessInit as SharedProcessInitMessage;
|
|
||||||
if (!spm) {
|
|
||||||
ws.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const connection: ReadWriteConnection = {
|
const connection: ReadWriteConnection = {
|
||||||
onMessage: (cb): void => {
|
onMessage: (cb): void => {
|
||||||
ws.addEventListener("message", (event) => cb(event.data));
|
ws.addEventListener("message", (event) => cb(event.data));
|
||||||
|
@ -44,7 +38,7 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
||||||
...options,
|
...options,
|
||||||
forkProvider: (message: NewSessionMessage): ChildProcess => {
|
forkProvider: (message: NewSessionMessage): ChildProcess => {
|
||||||
let proc: ChildProcess;
|
let proc: ChildProcess;
|
||||||
|
|
||||||
if (message.getIsBootstrapFork()) {
|
if (message.getIsBootstrapFork()) {
|
||||||
proc = forkModule(message.getCommand());
|
proc = forkModule(message.getCommand());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import "./fill/require";
|
import "./fill/require";
|
||||||
import "./fill/storageDatabase";
|
import "./fill/storageDatabase";
|
||||||
import "./fill/windowsService";
|
import "./fill/windowsService";
|
||||||
|
import * as paths from "./fill/paths";
|
||||||
|
import "./fill/dom";
|
||||||
|
import "./vscode.scss";
|
||||||
|
|
||||||
import { fork } from "child_process";
|
import { createConnection } from "net";
|
||||||
import { Client as IDEClient, IURI, IURIFactory } from "@coder/ide";
|
import { Client as IDEClient, IURI, IURIFactory } from "@coder/ide";
|
||||||
import { logger } from "@coder/logger";
|
|
||||||
|
|
||||||
import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu";
|
import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu";
|
||||||
import { LogLevel } from "vs/platform/log/common/log";
|
import { LogLevel } from "vs/platform/log/common/log";
|
||||||
|
@ -12,36 +14,42 @@ import { toLocalISOString } from "vs/base/common/date";
|
||||||
// import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
// import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
||||||
import { URI } from "vs/base/common/uri";
|
import { URI } from "vs/base/common/uri";
|
||||||
|
|
||||||
import { Protocol, ISharedProcessInitData } from "./protocol";
|
import { Protocol } from "vs/base/parts/ipc/node/ipc.net";
|
||||||
import * as paths from "./fill/paths";
|
|
||||||
import "./firefox";
|
|
||||||
|
|
||||||
export class Client extends IDEClient {
|
export class Client extends IDEClient {
|
||||||
|
|
||||||
private readonly sharedProcessLogger = logger.named("shr proc");
|
|
||||||
private readonly windowId = parseInt(toLocalISOString(new Date()).replace(/[-:.TZ]/g, ""), 10);
|
private readonly windowId = parseInt(toLocalISOString(new Date()).replace(/[-:.TZ]/g, ""), 10);
|
||||||
private readonly version = "hello"; // TODO: pull from package.json probably
|
|
||||||
private readonly bootstrapForkLocation = "/bootstrap"; // TODO: location.
|
|
||||||
public readonly protocolPromise: Promise<Protocol>;
|
public readonly protocolPromise: Promise<Protocol>;
|
||||||
private protoResolve: ((protocol: Protocol) => void) | undefined;
|
public protoResolve: ((protocol: Protocol) => void) | undefined;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
process.env.VSCODE_LOGS = "/tmp/vscode-online/logs"; // TODO: use tmpdir or get log directory from init data.
|
|
||||||
this.protocolPromise = new Promise((resolve): void => {
|
this.protocolPromise = new Promise((resolve): void => {
|
||||||
this.protoResolve = resolve;
|
this.protoResolve = resolve;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initialize(): Promise<void> {
|
protected initialize(): Promise<void> {
|
||||||
this.task("Start shared process", 5, async () => {
|
this.task("Connect to shared process", 5, async () => {
|
||||||
const protocol = await this.forkSharedProcess();
|
await new Promise((resolve, reject): void => {
|
||||||
this.protoResolve!(protocol);
|
const listener = this.onSharedProcessActive((data) => {
|
||||||
|
listener.dispose();
|
||||||
|
const socket = createConnection(data.socketPath, resolve);
|
||||||
|
socket.once("error", () => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
this.protoResolve!(new Protocol(socket));
|
||||||
|
});
|
||||||
|
});
|
||||||
}).catch(() => undefined);
|
}).catch(() => undefined);
|
||||||
|
|
||||||
registerContextMenuListener();
|
registerContextMenuListener();
|
||||||
|
|
||||||
return this.task("Start workbench", 1000, async (initData) => {
|
return this.task("Start workbench", 1000, async (initData) => {
|
||||||
|
paths.paths.appData = initData.dataDirectory;
|
||||||
|
paths.paths.defaultUserData = initData.dataDirectory;
|
||||||
|
|
||||||
const { startup } = require("./startup");
|
const { startup } = require("./startup");
|
||||||
await startup({
|
await startup({
|
||||||
machineId: "1",
|
machineId: "1",
|
||||||
|
@ -57,6 +65,33 @@ export class Client extends IDEClient {
|
||||||
folderUri: URI.file(initData.dataDirectory),
|
folderUri: URI.file(initData.dataDirectory),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Set notification service for retrying.
|
||||||
|
// this.retry.setNotificationService({
|
||||||
|
// prompt: (severity, message, buttons, onCancel) => {
|
||||||
|
// const handle = getNotificationService().prompt(severity, message, buttons, onCancel);
|
||||||
|
// return {
|
||||||
|
// close: () => handle.close(),
|
||||||
|
// updateMessage: (message) => handle.updateMessage(message),
|
||||||
|
// updateButtons: (buttons) => handle.updateActions({
|
||||||
|
// primary: buttons.map((button) => ({
|
||||||
|
// id: undefined,
|
||||||
|
// label: button.label,
|
||||||
|
// tooltip: undefined,
|
||||||
|
// class: undefined,
|
||||||
|
// enabled: true,
|
||||||
|
// checked: false,
|
||||||
|
// radio: false,
|
||||||
|
// dispose: () => undefined,
|
||||||
|
// run: () => {
|
||||||
|
// button.run();
|
||||||
|
// return Promise.resolve();
|
||||||
|
// },
|
||||||
|
// })),
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
// TODO: Set up clipboard context.
|
// TODO: Set up clipboard context.
|
||||||
// const workbench = workbenchShell.workbench;
|
// const workbench = workbenchShell.workbench;
|
||||||
// const contextKeys = workbench.workbenchParams.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
// const contextKeys = workbench.workbenchParams.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
||||||
|
@ -69,50 +104,6 @@ export class Client extends IDEClient {
|
||||||
}, this.initData);
|
}, this.initData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async forkSharedProcess(): Promise<Protocol> {
|
|
||||||
const childProcess = fork(this.bootstrapForkLocation, ["--shared"], {
|
|
||||||
env: {
|
|
||||||
"VSCODE_ALLOW_IO": "true",
|
|
||||||
"AMD_ENTRYPOINT": "vs/code/electron-browser/sharedProcess/sharedProcessClient",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.stderr.on("data", (data) => {
|
|
||||||
this.sharedProcessLogger.error("stderr: " + data);
|
|
||||||
});
|
|
||||||
|
|
||||||
const protocol = Protocol.fromProcess(childProcess);
|
|
||||||
await new Promise((resolve, reject): void => {
|
|
||||||
protocol.onClose(() => {
|
|
||||||
reject(new Error("unable to establish connection to shared process"));
|
|
||||||
});
|
|
||||||
|
|
||||||
const listener = protocol.onMessage((message) => {
|
|
||||||
const messageStr = message.toString();
|
|
||||||
this.sharedProcessLogger.debug(messageStr);
|
|
||||||
switch (messageStr) {
|
|
||||||
case "handshake:hello":
|
|
||||||
protocol.send(Buffer.from(JSON.stringify({
|
|
||||||
// Using the version so if we get a new mount, it spins up a new
|
|
||||||
// shared process.
|
|
||||||
socketPath: `/tmp/vscode-online/shared-${this.version}.sock`,
|
|
||||||
serviceUrl: "", // TODO
|
|
||||||
logsDir: process.env.VSCODE_LOGS,
|
|
||||||
windowId: this.windowId,
|
|
||||||
logLevel: LogLevel.Info,
|
|
||||||
} as ISharedProcessInitData)));
|
|
||||||
break;
|
|
||||||
case "handshake:ready":
|
|
||||||
listener.dispose();
|
|
||||||
resolve();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return protocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected createUriFactory(): IURIFactory {
|
protected createUriFactory(): IURIFactory {
|
||||||
return {
|
return {
|
||||||
// TODO: not sure why this is an error.
|
// TODO: not sure why this is an error.
|
||||||
|
@ -126,8 +117,3 @@ export class Client extends IDEClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const client = new Client();
|
export const client = new Client();
|
||||||
|
|
||||||
client.initData.then((initData) => {
|
|
||||||
paths.appData = initData.dataDirectory;
|
|
||||||
paths.defaultUserData = initData.dataDirectory;
|
|
||||||
});
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "./firefox.scss";
|
// Firefox has no implementation of toElement.
|
||||||
|
|
||||||
if (!("toElement" in MouseEvent.prototype)) {
|
if (!("toElement" in MouseEvent.prototype)) {
|
||||||
Object.defineProperty(MouseEvent.prototype, "toElement", {
|
Object.defineProperty(MouseEvent.prototype, "toElement", {
|
||||||
get: function (): EventTarget | null {
|
get: function (): EventTarget | null {
|
|
@ -1,4 +1,4 @@
|
||||||
const paths = {
|
export const paths = {
|
||||||
appData: "/tmp",
|
appData: "/tmp",
|
||||||
defaultUserData: "/tmp",
|
defaultUserData: "/tmp",
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
import { ChildProcess } from "child_process";
|
|
||||||
import { EventEmitter } from "events";
|
|
||||||
import { Protocol as VSProtocol } from "vs/base/parts/ipc/node/ipc.net";
|
|
||||||
import { LogLevel } from "vs/platform/log/common/log";
|
|
||||||
|
|
||||||
export interface ISharedProcessInitData {
|
|
||||||
socketPath: string;
|
|
||||||
serviceUrl: string;
|
|
||||||
logsDir: string;
|
|
||||||
windowId: number;
|
|
||||||
logLevel: LogLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStdio {
|
|
||||||
onMessage: (cb: (data: string | Buffer) => void) => void;
|
|
||||||
sendMessage: (data: string | Buffer) => void;
|
|
||||||
onExit?: (cb: () => void) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of net.Socket that uses stdio streams.
|
|
||||||
*/
|
|
||||||
class Socket {
|
|
||||||
|
|
||||||
private readonly emitter: EventEmitter;
|
|
||||||
|
|
||||||
public constructor(private readonly stdio: IStdio, ignoreFirst: boolean = false) {
|
|
||||||
this.emitter = new EventEmitter();
|
|
||||||
|
|
||||||
let first = true;
|
|
||||||
stdio.onMessage((data) => {
|
|
||||||
if (ignoreFirst && first) {
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.emitter.emit("data", Buffer.from(data.toString()));
|
|
||||||
});
|
|
||||||
if (stdio.onExit) {
|
|
||||||
stdio.onExit(() => {
|
|
||||||
this.emitter.emit("close");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeListener(event: string, listener: () => void): void {
|
|
||||||
this.emitter.removeListener(event, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public once(event: string, listener: () => void): void {
|
|
||||||
this.emitter.once(event, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public on(event: string, listener: () => void): void {
|
|
||||||
this.emitter.on(event, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public end(): void {
|
|
||||||
// TODO: figure it out
|
|
||||||
}
|
|
||||||
|
|
||||||
public get destroyed(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public write(data: string | Buffer): void {
|
|
||||||
this.stdio.sendMessage(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A protocol around a process, stream, or worker.
|
|
||||||
*/
|
|
||||||
export class Protocol extends VSProtocol {
|
|
||||||
|
|
||||||
public static fromProcess(childProcess: ChildProcess): Protocol {
|
|
||||||
return Protocol.fromStdio({
|
|
||||||
onMessage: (cb): void => {
|
|
||||||
childProcess.stdout.on("data", (data: string | Buffer) => {
|
|
||||||
cb(data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
sendMessage: (data): void => {
|
|
||||||
childProcess.stdin.write(data);
|
|
||||||
},
|
|
||||||
onExit: (cb): void => {
|
|
||||||
childProcess.on("exit", cb);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromStream(
|
|
||||||
inStream: { on: (event: "data", cb: (b: string | Buffer) => void) => void },
|
|
||||||
outStream: { write: (b: string | Buffer) => void },
|
|
||||||
): Protocol {
|
|
||||||
return Protocol.fromStdio({
|
|
||||||
onMessage: (cb): void => {
|
|
||||||
inStream.on("data", (data) => {
|
|
||||||
cb(data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
sendMessage: (data): void => {
|
|
||||||
outStream.write(data);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromWorker(worker: {
|
|
||||||
onmessage: (event: MessageEvent) => void;
|
|
||||||
postMessage: (data: string, origin?: string | string[]) => void;
|
|
||||||
}, ignoreFirst: boolean = false): Protocol {
|
|
||||||
return Protocol.fromStdio({
|
|
||||||
onMessage: (cb): void => {
|
|
||||||
worker.onmessage = (event: MessageEvent): void => {
|
|
||||||
cb(event.data);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
sendMessage: (data): void => {
|
|
||||||
worker.postMessage(data.toString());
|
|
||||||
},
|
|
||||||
}, ignoreFirst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromStdio(stdio: IStdio, ignoreFirst?: boolean): Protocol {
|
|
||||||
return new Protocol(new Socket(stdio, ignoreFirst));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
// These use -webkit-margin-before/after which don't work.
|
||||||
|
.monaco-workbench > .part > .title > .title-label h2,
|
||||||
|
.monaco-panel-view .panel > .panel-header h3.title {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Using @supports to keep the Firefox fixes completely separate from vscode's
|
// Using @supports to keep the Firefox fixes completely separate from vscode's
|
||||||
// CSS that is tailored for Chrome.
|
// CSS that is tailored for Chrome.
|
||||||
@supports (-moz-appearance:none) {
|
@supports (-moz-appearance:none) {
|
||||||
/* Fix buttons getting cut off on notifications. */
|
// Fix buttons getting cut off on notifications.
|
||||||
.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-button.monaco-text-button {
|
.monaco-workbench .notifications-list-container .notification-list-item .notification-list-item-buttons-container .monaco-button.monaco-text-button {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: auto;
|
width: auto;
|
|
@ -44,37 +44,6 @@ module.exports = (env) => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
|
||||||
loader: "string-replace-loader",
|
|
||||||
test: /vs\/loader\.js/,
|
|
||||||
options: {
|
|
||||||
multiple: [
|
|
||||||
{
|
|
||||||
search: "var recorder = moduleManager.getRecorder\\(\\);",
|
|
||||||
replace: `
|
|
||||||
var recorder = moduleManager.getRecorder();
|
|
||||||
const context = require.context("../", true, /.*/);
|
|
||||||
if (scriptSrc.indexOf("file:///") !== -1) {
|
|
||||||
const vsSrc = scriptSrc.split("file:///")[1].split(".js")[0];
|
|
||||||
if (vsSrc && vsSrc.startsWith("vs/")) {
|
|
||||||
scriptSrc = \`node|./\${vsSrc}\`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
flags: "g",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
search: "nodeRequire\\(",
|
|
||||||
replace: "require(",
|
|
||||||
flags: "g",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
search: "moduleExports_1 = require\\(",
|
|
||||||
replace: "moduleExports_1 = context(",
|
|
||||||
flags: "g",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}, {
|
}, {
|
||||||
test: /\.wasm$/,
|
test: /\.wasm$/,
|
||||||
type: "javascript/auto",
|
type: "javascript/auto",
|
||||||
|
@ -120,4 +89,4 @@ if (scriptSrc.indexOf("file:///") !== -1) {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,11 @@ module.exports = merge({
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
|
node: {
|
||||||
|
module: "empty",
|
||||||
|
crypto: "empty",
|
||||||
|
tls: "empty",
|
||||||
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"gc-signals": path.join(fills, "empty.ts"),
|
"gc-signals": path.join(fills, "empty.ts"),
|
||||||
|
@ -51,6 +56,10 @@ module.exports = merge({
|
||||||
"vscode-sqlite3": path.join(fills, "empty.ts"),
|
"vscode-sqlite3": path.join(fills, "empty.ts"),
|
||||||
"tls": path.join(fills, "empty.ts"),
|
"tls": path.join(fills, "empty.ts"),
|
||||||
"native-is-elevated": path.join(fills, "empty.ts"),
|
"native-is-elevated": path.join(fills, "empty.ts"),
|
||||||
|
"native-watchdog": path.join(fills, "empty.ts"),
|
||||||
|
"dns": path.join(fills, "empty.ts"),
|
||||||
|
"console": path.join(fills, "empty.ts"),
|
||||||
|
"readline": path.join(fills, "empty.ts"),
|
||||||
|
|
||||||
"crypto": "crypto-browserify",
|
"crypto": "crypto-browserify",
|
||||||
"http": "http-browserify",
|
"http": "http-browserify",
|
||||||
|
|
|
@ -1,3 +1,99 @@
|
||||||
|
diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||||
|
index 457818a975..ad45ffe58a 100644
|
||||||
|
--- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||||
|
+++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||||
|
@@ -194,3 +194,5 @@ async function handshake(configuration: ISharedProcessConfiguration): Promise<vo
|
||||||
|
main(server, data, configuration);
|
||||||
|
ipcRenderer.send('handshake:im ready');
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+startup({ machineId: "1" });
|
||||||
|
diff --git a/src/vs/loader.js b/src/vs/loader.js
|
||||||
|
index 2bf7fe37d7..81cc668f12 100644
|
||||||
|
--- a/src/vs/loader.js
|
||||||
|
+++ b/src/vs/loader.js
|
||||||
|
@@ -667,10 +667,10 @@ var AMDLoader;
|
||||||
|
}
|
||||||
|
this._didInitialize = true;
|
||||||
|
// capture node modules
|
||||||
|
- this._fs = nodeRequire('fs');
|
||||||
|
- this._vm = nodeRequire('vm');
|
||||||
|
- this._path = nodeRequire('path');
|
||||||
|
- this._crypto = nodeRequire('crypto');
|
||||||
|
+ this._fs = require('fs');
|
||||||
|
+ this._vm = require('vm');
|
||||||
|
+ this._path = require('path');
|
||||||
|
+ this._crypto = require('crypto');
|
||||||
|
};
|
||||||
|
// patch require-function of nodejs such that we can manually create a script
|
||||||
|
// from cached data. this is done by overriding the `Module._compile` function
|
||||||
|
@@ -731,11 +731,18 @@ var AMDLoader;
|
||||||
|
this._init(nodeRequire);
|
||||||
|
this._initNodeRequire(nodeRequire, moduleManager);
|
||||||
|
var recorder = moduleManager.getRecorder();
|
||||||
|
+ const context = require.context("../", true, /.*/);
|
||||||
|
+ if (scriptSrc.indexOf("file:///") !== -1) {
|
||||||
|
+ const vsSrc = scriptSrc.split("file:///")[1].split(".js")[0];
|
||||||
|
+ if (vsSrc && vsSrc.startsWith("vs/")) {
|
||||||
|
+ scriptSrc = `node|./${vsSrc}`;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
if (/^node\|/.test(scriptSrc)) {
|
||||||
|
var pieces = scriptSrc.split('|');
|
||||||
|
var moduleExports_1 = null;
|
||||||
|
try {
|
||||||
|
- moduleExports_1 = nodeRequire(pieces[1]);
|
||||||
|
+ moduleExports_1 = context(pieces[1]);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
errorback(err);
|
||||||
|
diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts
|
||||||
|
index 9e6a94bbd2..9e7f9cb595 100644
|
||||||
|
--- a/src/vs/platform/storage/node/storageService.ts
|
||||||
|
+++ b/src/vs/platform/storage/node/storageService.ts
|
||||||
|
@@ -89,6 +89,9 @@ export class StorageService extends Disposable implements IStorageService {
|
||||||
|
private initializeGlobalStorage(): Thenable<void> {
|
||||||
|
mark('willInitGlobalStorage');
|
||||||
|
|
||||||
|
+ // TODO: shouldn't reject
|
||||||
|
+ return Promise.reject(new Error("nope"));
|
||||||
|
+
|
||||||
|
return this.globalStorage.init().then(() => {
|
||||||
|
mark('didInitGlobalStorage');
|
||||||
|
}, error => {
|
||||||
|
@@ -605,4 +608,4 @@ export class DelegatingStorageService extends Disposable implements IStorageServ
|
||||||
|
private convertScope(scope: StorageScope): StorageLegacyScope {
|
||||||
|
return scope === StorageScope.GLOBAL ? StorageLegacyScope.GLOBAL : StorageLegacyScope.WORKSPACE;
|
||||||
|
}
|
||||||
|
-}
|
||||||
|
\ No newline at end of file
|
||||||
|
+}
|
||||||
|
diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts
|
||||||
|
index a43d63aa51..4c6df2fcd9 100644
|
||||||
|
--- a/src/vs/workbench/electron-browser/main.ts
|
||||||
|
+++ b/src/vs/workbench/electron-browser/main.ts
|
||||||
|
@@ -147,13 +147,14 @@ function openWorkbench(configuration: IWindowConfiguration): Promise<void> {
|
||||||
|
shell.open();
|
||||||
|
|
||||||
|
// Inform user about loading issues from the loader
|
||||||
|
- (<any>self).require.config({
|
||||||
|
- onError: err => {
|
||||||
|
- if (err.errorCode === 'load') {
|
||||||
|
- shell.onUnexpectedError(new Error(nls.localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err))));
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- });
|
||||||
|
+ // TODO: how to make this work
|
||||||
|
+ // (<any>self).require.config({
|
||||||
|
+ // onError: err => {
|
||||||
|
+ // if (err.errorCode === 'load') {
|
||||||
|
+ // shell.onUnexpectedError(new Error(nls.localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err))));
|
||||||
|
+ // }
|
||||||
|
+ // }
|
||||||
|
+ // });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||||
index 7b4e8721ac..8f26dc2f28 100644
|
index 7b4e8721ac..8f26dc2f28 100644
|
||||||
--- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
--- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||||
|
|
Loading…
Reference in New Issue