From 227474c1564d12cad021a518562bce32792b0f57 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 21 Feb 2019 12:06:15 -0600 Subject: [PATCH 1/4] Fix storage path ending replacement --- packages/vscode/src/fill/storageDatabase.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/vscode/src/fill/storageDatabase.ts b/packages/vscode/src/fill/storageDatabase.ts index ec085dd4d..547f140f5 100644 --- a/packages/vscode/src/fill/storageDatabase.ts +++ b/packages/vscode/src/fill/storageDatabase.ts @@ -14,10 +14,11 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase { public readonly onDidChangeItemsExternal = Event.None; private readonly items = new Map(); private fetched: boolean = false; + private readonly path: string; - public constructor(private readonly path: string) { - path = path.replace(/\.vscdb$/, ".json"); - logger.debug("Setting up storage", field("path", path)); + public constructor(path: string) { + this.path = path.replace(/\.vscdb$/, ".json"); + logger.debug("Setting up storage", field("path", this.path)); window.addEventListener("unload", () => { if (!navigator.sendBeacon) { throw new Error("cannot save state"); @@ -39,7 +40,7 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase { this.items.set(key, json[key]); }); } catch (error) { - if (error.code && error.code !== "ENOENT") { + if (error.code !== "ENOENT") { throw error; } } From e4150de1544b5db5a397dd3ff51f1a40bec461dd Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 21 Feb 2019 12:43:49 -0600 Subject: [PATCH 2/4] Fix handleExternalDrop event --- packages/vscode/src/client.ts | 4 ++-- scripts/vscode.patch | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vscode/src/client.ts b/packages/vscode/src/client.ts index 0a489dac6..a087d1988 100644 --- a/packages/vscode/src/client.ts +++ b/packages/vscode/src/client.ts @@ -41,9 +41,9 @@ export class Client extends IdeClient { return this._builtInExtensionsDirectory; } - public async handleExternalDrop(target: ExplorerItem | ExplorerModel, originalEvent: DragMouseEvent): Promise { + public async handleExternalDrop(target: ExplorerItem | ExplorerModel, originalEvent: DragEvent): Promise { await this.upload.uploadDropped( - originalEvent.browserEvent as DragEvent, + originalEvent, (target instanceof ExplorerItem ? target : target.roots[0]).resource, ); } diff --git a/scripts/vscode.patch b/scripts/vscode.patch index dc0aed015..6f2fa8e0c 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -129,11 +129,11 @@ index 81954344b9..2bdce9603e 100644 - if (!fs.existsSync(this.adapterExecutable.command)) { + if (!(await require("util").promisify(fs.exists)(this.adapterExecutable.command))) { diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts -index e66f74f034..aca6f509b0 100644 +index e66f74f034..759ffe0cef 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts @@ -586,0 +587 @@ export class FileDragAndDrop implements ITreeDragAndDrop { -+ return (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.handleExternalDrop(target, originalEvent as any); ++ return (require('vs/../../../../packages/vscode') as typeof import('vs/../../../../packages/vscode')).client.handleExternalDrop(target, originalEvent); diff --git a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts index 4015c9cd5d..bebdb25f6c 100644 --- a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts From fe107802e3830f70890bb5ca58cc1f5410af4a6d Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 21 Feb 2019 13:29:08 -0600 Subject: [PATCH 3/4] Fix stringifying Uint8Array --- packages/protocol/src/common/util.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/protocol/src/common/util.ts b/packages/protocol/src/common/util.ts index 4c995e42a..5cb9b5cc5 100644 --- a/packages/protocol/src/common/util.ts +++ b/packages/protocol/src/common/util.ts @@ -31,6 +31,7 @@ export type IEncodingOptionsCallback = IEncodingOptions | ((err: NodeJS.ErrnoExc */ export const stringify = (arg: any): string => { // tslint:disable-line no-any if (arg instanceof Error) { + // Errors don't stringify at all. They just become "{}". return JSON.stringify({ type: "Error", data: { @@ -39,6 +40,15 @@ export const stringify = (arg: any): string => { // tslint:disable-line no-any stack: arg.stack, }, }); + } else if (arg instanceof Uint8Array) { + // With stringify, these get turned into objects with each index becoming a + // key for some reason. Then trying to do something like write that data + // results in [object Object] being written. Stringify them like a Buffer + // instead. + return JSON.stringify({ + type: "Buffer", + data: Array.from(arg), + }); } return JSON.stringify(arg); From 7edf797efc2ef1d6e996afd1322dc4cf3df82f58 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 21 Feb 2019 14:09:07 -0600 Subject: [PATCH 4/4] Parse args sent through evaluation function Previously they'd go in still stringified so we didn't get a chance to convert buffer objects back to buffers, for example, making things like `fs.write` write `[object Object]` to files. --- packages/ide/test/fs.test.ts | 11 +++++++++-- packages/ide/test/net.test.ts | 9 ++++++++- packages/protocol/src/browser/client.ts | 2 +- packages/protocol/src/node/evaluate.ts | 8 ++------ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/ide/test/fs.test.ts b/packages/ide/test/fs.test.ts index c4e84ad04..856ae476d 100644 --- a/packages/ide/test/fs.test.ts +++ b/packages/ide/test/fs.test.ts @@ -11,7 +11,7 @@ const fs = require("../src/fill/fs") as typeof import("fs"); describe("fs", () => { let i = 0; - const coderDir = path.join(os.tmpdir(), "coder"); + const coderDir = path.join(os.tmpdir(), "coder", "fs"); const testFile = path.join(__dirname, "fs.test.ts"); const tmpFile = (): string => path.join(coderDir, `${i++}`); const createTmpFile = async (): Promise => { @@ -22,6 +22,13 @@ describe("fs", () => { }; beforeAll(async () => { + try { + await util.promisify(nativeFs.mkdir)(path.dirname(coderDir)); + } catch (error) { + if (error.code !== "EEXIST") { + throw error; + } + } await util.promisify(rimraf)(coderDir); await util.promisify(nativeFs.mkdir)(coderDir); }); @@ -332,7 +339,7 @@ describe("fs", () => { describe("mkdtemp", () => { it("should create temp dir", async () => { await expect(util.promisify(fs.mkdtemp)(coderDir + "/")) - .resolves.toMatch(/^\/tmp\/coder\/[a-zA-Z0-9]{6}/); + .resolves.toMatch(/^\/tmp\/coder\/fs\/[a-zA-Z0-9]{6}/); }); }); diff --git a/packages/ide/test/net.test.ts b/packages/ide/test/net.test.ts index fd2088319..964b4ffe0 100644 --- a/packages/ide/test/net.test.ts +++ b/packages/ide/test/net.test.ts @@ -12,10 +12,17 @@ const net = require("../src/fill/net") as typeof import("net"); describe("net", () => { let i = 0; - const coderDir = path.join(os.tmpdir(), "coder"); + const coderDir = path.join(os.tmpdir(), "coder", "net"); const tmpFile = (): string => path.join(coderDir, `socket.${i++}`); beforeAll(async () => { + try { + await util.promisify(fs.mkdir)(path.dirname(coderDir)); + } catch (error) { + if (error.code !== "EEXIST") { + throw error; + } + } await util.promisify(rimraf)(coderDir); await util.promisify(fs.mkdir)(coderDir); }); diff --git a/packages/protocol/src/browser/client.ts b/packages/protocol/src/browser/client.ts index d436057ae..ff621a748 100644 --- a/packages/protocol/src/browser/client.ts +++ b/packages/protocol/src/browser/client.ts @@ -4,7 +4,7 @@ import { logger, field } from "@coder/logger"; import { ReadWriteConnection, InitData, OperatingSystem, SharedProcessData } from "../common/connection"; import { Disposer, stringify, parse } from "../common/util"; import { NewEvalMessage, ServerMessage, EvalDoneMessage, EvalFailedMessage, ClientMessage, WorkingInitMessage, EvalEventMessage } from "../proto"; -import { ActiveEval } from "./command"; +import { ActiveEval } from "./evaluate"; /** * Client accepts an arbitrary connection intended to communicate with the Server. diff --git a/packages/protocol/src/node/evaluate.ts b/packages/protocol/src/node/evaluate.ts index fa441be52..4e9088e2e 100644 --- a/packages/protocol/src/node/evaluate.ts +++ b/packages/protocol/src/node/evaluate.ts @@ -12,11 +12,6 @@ export interface ActiveEvaluation { declare var __non_webpack_require__: typeof require; export const evaluate = (connection: SendableConnection, message: NewEvalMessage, onDispose: () => void): ActiveEvaluation | void => { - const argStr: string[] = []; - message.getArgsList().forEach((value) => { - argStr.push(value); - }); - /** * Send the response and call onDispose. */ @@ -94,11 +89,12 @@ export const evaluate = (connection: SendableConnection, message: NewEvalMessage process: { env: process.env, }, + args: message.getArgsList().map(parse), }; let value: any; // tslint:disable-line no-any try { - const code = `(${message.getFunction()})(${eventEmitter ? "eventEmitter, " : ""}${argStr.join(",")});`; + const code = `(${message.getFunction()})(${eventEmitter ? "eventEmitter, " : ""}...args);`; value = vm.runInNewContext(code, sandbox, { // If the code takes longer than this to return, it is killed and throws. timeout: message.getTimeout() || 15000,