Update node to 10.15.1 (#472)
* Update Node to 10.15.1 * Remove string replace that was used for oclif * Update nbin * Package node-pty and spdlog with nbin * Label stderr/stdout from shared process * Remove fork override * Prevent "already disposed" errors when trying to kill disposed proxies * Include spdlog dependencies * Shim /node_modules * Add node_modules to Docker ignore It keeps using my already-built .node files which results in a mismatching GLIBC version error. * Update nbin
This commit is contained in:
@ -8,9 +8,8 @@ import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as WebSocket from "ws";
|
||||
import { buildDir, cacheHome, dataHome, isCli, serveStatic } from "./constants";
|
||||
import { setup as setupNativeModules } from "./modules";
|
||||
import { createApp } from "./server";
|
||||
import { forkModule, requireFork, requireModule } from "./vscode/bootstrapFork";
|
||||
import { forkModule, requireModule } from "./vscode/bootstrapFork";
|
||||
import { SharedProcess, SharedProcessState } from "./vscode/sharedProcess";
|
||||
import opn = require("opn");
|
||||
|
||||
@ -31,7 +30,6 @@ commander.version(process.env.VERSION || "development")
|
||||
.option("-H, --allow-http", "Allow http connections.", false)
|
||||
.option("-P, --password <value>", "Specify a password for authentication.")
|
||||
.option("--bootstrap-fork <name>", "Used for development. Never set.")
|
||||
.option("--fork <name>", "Used for development. Never set.")
|
||||
.option("--extra-args <args>", "Used for development. Never set.")
|
||||
.arguments("Specify working directory.")
|
||||
.parse(process.argv);
|
||||
@ -39,6 +37,7 @@ commander.version(process.env.VERSION || "development")
|
||||
Error.stackTraceLimit = Infinity;
|
||||
if (isCli) {
|
||||
require("nbin").shimNativeFs(buildDir);
|
||||
require("nbin").shimNativeFs("/node_modules");
|
||||
}
|
||||
// Makes strings or numbers bold in stdout
|
||||
const bold = (text: string | number): string | number => {
|
||||
@ -63,7 +62,6 @@ const bold = (text: string | number): string | number => {
|
||||
readonly certKey?: string;
|
||||
|
||||
readonly bootstrapFork?: string;
|
||||
readonly fork?: string;
|
||||
readonly extraArgs?: string;
|
||||
};
|
||||
|
||||
@ -75,6 +73,7 @@ const bold = (text: string | number): string | number => {
|
||||
const dataDir = path.resolve(options.userDataDir || options.dataDir || path.join(dataHome, "code-server"));
|
||||
const extensionsDir = options.extensionsDir ? path.resolve(options.extensionsDir) : path.resolve(dataDir, "extensions");
|
||||
const workingDir = path.resolve(args[0] || process.cwd());
|
||||
const dependenciesDir = path.join(os.tmpdir(), "code-server/dependencies");
|
||||
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
const oldDataDir = path.resolve(path.join(os.homedir(), ".code-server"));
|
||||
@ -89,9 +88,22 @@ const bold = (text: string | number): string | number => {
|
||||
fse.mkdirp(dataDir),
|
||||
fse.mkdirp(extensionsDir),
|
||||
fse.mkdirp(workingDir),
|
||||
fse.mkdirp(dependenciesDir),
|
||||
]);
|
||||
|
||||
setupNativeModules(dataDir);
|
||||
const unpackExecutable = (binaryName: string): void => {
|
||||
const memFile = path.join(isCli ? buildDir! : path.join(__dirname, ".."), "build/dependencies", binaryName);
|
||||
const diskFile = path.join(dependenciesDir, binaryName);
|
||||
if (!fse.existsSync(diskFile)) {
|
||||
fse.writeFileSync(diskFile, fse.readFileSync(memFile));
|
||||
}
|
||||
fse.chmodSync(diskFile, "755");
|
||||
};
|
||||
|
||||
unpackExecutable("rg");
|
||||
// tslint:disable-next-line no-any
|
||||
(<any>global).RIPGREP_LOCATION = path.join(dependenciesDir, "rg");
|
||||
|
||||
const builtInExtensionsDir = path.resolve(buildDir || path.join(__dirname, ".."), "build/extensions");
|
||||
if (options.bootstrapFork) {
|
||||
const modulePath = options.bootstrapFork;
|
||||
@ -106,13 +118,7 @@ const bold = (text: string | number): string | number => {
|
||||
process.argv[i + 2] = arg;
|
||||
});
|
||||
|
||||
return requireModule(modulePath, dataDir, builtInExtensionsDir);
|
||||
}
|
||||
|
||||
if (options.fork) {
|
||||
const modulePath = options.fork;
|
||||
|
||||
return requireFork(modulePath, JSON.parse(options.extraArgs!), builtInExtensionsDir);
|
||||
return requireModule(modulePath, builtInExtensionsDir);
|
||||
}
|
||||
|
||||
const logDir = path.join(cacheHome, "code-server/logs", new Date().toISOString().replace(/[-:.TZ]/g, ""));
|
||||
@ -224,14 +230,7 @@ const bold = (text: string | number): string | number => {
|
||||
return forkModule(options.env.AMD_ENTRYPOINT, args, options, dataDir);
|
||||
}
|
||||
|
||||
if (isCli) {
|
||||
return spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--extra-args", JSON.stringify(args), "--data-dir", dataDir], {
|
||||
...options,
|
||||
stdio: [null, null, null, "ipc"],
|
||||
});
|
||||
} else {
|
||||
return fork(modulePath, args, options);
|
||||
}
|
||||
return fork(modulePath, args, options);
|
||||
},
|
||||
},
|
||||
password,
|
||||
|
@ -1,53 +0,0 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as os from "os";
|
||||
import { isCli, buildDir } from "./constants";
|
||||
|
||||
/**
|
||||
* Handling of native modules within the CLI
|
||||
*/
|
||||
export const setup = (dataDirectory: string): void => {
|
||||
path.resolve(dataDirectory, "dependencies").split(path.sep).reduce((parentDir, childDir) => {
|
||||
const currentDir = path.join(parentDir, childDir);
|
||||
try {
|
||||
fs.mkdirSync(currentDir);
|
||||
} catch (ex) {
|
||||
if (ex.code !== "EEXIST" && ex.code !== "EISDIR" && ex.code !== "ENOENT") {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
return currentDir;
|
||||
}, os.platform() === "win32" ? undefined! : path.sep); // Might need path.sep here for linux. Having it for windows causes an error because \C:\Users ...
|
||||
|
||||
const unpackModule = (moduleName: string, markExecutable: boolean = false): void => {
|
||||
const memFile = path.join(isCli ? buildDir! : path.join(__dirname, ".."), "build/dependencies", moduleName);
|
||||
const diskFile = path.join(dataDirectory, "dependencies", moduleName);
|
||||
if (!fs.existsSync(diskFile)) {
|
||||
fs.writeFileSync(diskFile, fs.readFileSync(memFile));
|
||||
}
|
||||
if (markExecutable) {
|
||||
fs.chmodSync(diskFile, "755");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* We need to unpack node-pty and patch its `loadNative` function to require our unpacked pty.node
|
||||
* If pty.node isn't unpacked a SIGSEGV is thrown and the application exits. The exact reasoning
|
||||
* for this is unknown ATM, but this patch works around it.
|
||||
*/
|
||||
unpackModule("pty.node");
|
||||
unpackModule("spdlog.node");
|
||||
unpackModule("rg", true);
|
||||
// const nodePtyUtils = require("../../protocol/node_modules/node-pty-prebuilt/lib/utils") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/utils");
|
||||
// tslint:disable-next-line:no-any
|
||||
// nodePtyUtils.loadNative = (modName: string): any => {
|
||||
// return (typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require)(path.join(dataDirectory, "dependencies", modName + ".node"));
|
||||
// };
|
||||
(<any>global).RIPGREP_LOCATION = path.join(dataDirectory, "dependencies", "rg");
|
||||
(<any>global).NODEPTY_LOCATION = path.join(dataDirectory, "dependencies", "pty.node");
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>global).SPDLOG_LOCATION = path.join(dataDirectory, "dependencies", "spdlog.node");
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
require("../../protocol/node_modules/node-pty-prebuilt/lib/index") as typeof import("../../protocol/node_modules/node-pty-prebuilt/src/index");
|
||||
};
|
@ -42,54 +42,13 @@ const requireFilesystemModule = (id: string, builtInExtensionsDir: string): any
|
||||
return customMod.require(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called from forking a module
|
||||
*/
|
||||
export const requireFork = (modulePath: string, args: string[], builtInExtensionsDir: string): void => {
|
||||
const Module = require("module") as typeof import("module");
|
||||
const oldRequire = Module.prototype.require;
|
||||
// tslint:disable-next-line:no-any
|
||||
const oldLoad = (Module as any)._findPath;
|
||||
// @ts-ignore
|
||||
(Module as any)._findPath = function (request, parent, isMain): any {
|
||||
const lookupPaths = oldLoad.call(this, request, parent, isMain);
|
||||
|
||||
return lookupPaths;
|
||||
};
|
||||
// tslint:disable-next-line:no-any
|
||||
Module.prototype.require = function (id: string): any {
|
||||
if (id === "typescript") {
|
||||
return require("typescript");
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
return oldRequire.call(this, id as any);
|
||||
};
|
||||
|
||||
if (!process.send) {
|
||||
throw new Error("No IPC messaging initialized");
|
||||
}
|
||||
|
||||
process.argv = ["", "", ...args];
|
||||
requireFilesystemModule(modulePath, builtInExtensionsDir);
|
||||
|
||||
if (ipcMsgBuffer && ipcMsgListener) {
|
||||
process.removeListener("message", ipcMsgListener);
|
||||
// tslint:disable-next-line:no-any
|
||||
ipcMsgBuffer.forEach((i) => process.emit("message" as any, i as any));
|
||||
ipcMsgBuffer = undefined;
|
||||
ipcMsgListener = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const requireModule = (modulePath: string, dataDir: string, builtInExtensionsDir: string): void => {
|
||||
export const requireModule = (modulePath: string, builtInExtensionsDir: string): void => {
|
||||
process.env.AMD_ENTRYPOINT = modulePath;
|
||||
const xml = require("xhr2");
|
||||
xml.XMLHttpRequest.prototype._restrictedHeaders["user-agent"] = false;
|
||||
// tslint:disable-next-line no-any this makes installing extensions work.
|
||||
(global as any).XMLHttpRequest = xml.XMLHttpRequest;
|
||||
|
||||
const mod = require("module") as typeof import("module");
|
||||
const promiseFinally = require("promise.prototype.finally") as { shim: () => void };
|
||||
promiseFinally.shim();
|
||||
/**
|
||||
@ -102,16 +61,7 @@ export const requireModule = (modulePath: string, dataDir: string, builtInExtens
|
||||
};
|
||||
|
||||
if (isCli) {
|
||||
/**
|
||||
* Needed for properly forking external modules within the CLI
|
||||
*/
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>cp).fork = (modulePath: string, args: ReadonlyArray<string> = [], options?: cp.ForkOptions): cp.ChildProcess => {
|
||||
return cp.spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--extra-args", JSON.stringify(args), "--data-dir", dataDir], {
|
||||
...options,
|
||||
stdio: [null, null, null, "ipc"],
|
||||
});
|
||||
};
|
||||
process.env.NBIN_BYPASS = "true";
|
||||
}
|
||||
|
||||
const baseDir = path.join(buildDir, "build");
|
||||
|
@ -8,7 +8,7 @@ import { StdioIpcHandler } from "../ipc";
|
||||
import { ParsedArgs } from "vs/platform/environment/common/environment";
|
||||
import { Emitter } from "@coder/events/src";
|
||||
import { retry } from "@coder/ide/src/retry";
|
||||
import { logger, Level } from "@coder/logger";
|
||||
import { logger, field, Level } from "@coder/logger";
|
||||
|
||||
export enum SharedProcessState {
|
||||
Stopped,
|
||||
@ -127,13 +127,13 @@ export class SharedProcess {
|
||||
activeProcess.on("exit", doReject);
|
||||
|
||||
activeProcess.stdout.on("data", (data) => {
|
||||
logger.trace(data.toString());
|
||||
logger.trace("stdout", field("data", data.toString()));
|
||||
});
|
||||
|
||||
activeProcess.stderr.on("data", (data) => {
|
||||
// Warn instead of error to prevent panic. It's unlikely stderr here is
|
||||
// about anything critical to the functioning of the editor.
|
||||
logger.warn(data.toString());
|
||||
logger.warn("stderr", field("data", data.toString()));
|
||||
});
|
||||
|
||||
this.ipcHandler = new StdioIpcHandler(activeProcess);
|
||||
|
Reference in New Issue
Block a user