@@ -8,10 +8,10 @@ import * as path from "path"
8
8
import { WebsocketRequest } from "../../../typings/pluginapi"
9
9
import { logError } from "../../common/util"
10
10
import { CodeArgs , toCodeArgs } from "../cli"
11
- import { isDevMode } from "../constants"
11
+ import { isDevMode , vsRootPath } from "../constants"
12
12
import { authenticated , ensureAuthenticated , ensureOrigin , redirect , replaceTemplates , self } from "../http"
13
13
import { SocketProxyProvider } from "../socket"
14
- import { isFile , loadAMDModule } from "../util"
14
+ import { isFile } from "../util"
15
15
import { Router as WsRouter } from "../wsRouter"
16
16
17
17
export const router = express . Router ( )
@@ -31,11 +31,46 @@ export interface IVSCodeServerAPI {
31
31
dispose ( ) : void
32
32
}
33
33
34
- // See ../../../lib/vscode/src/vs/server/node/server.main.ts:72.
35
- export type CreateServer = ( address : string | net . AddressInfo | null , args : CodeArgs ) => Promise < IVSCodeServerAPI >
34
+ /**
35
+ * VS Code's CLI entrypoint (../../../lib/vscode/src/server-main.js).
36
+ *
37
+ * Normally VS Code will run `node server-main.js` which starts either the web
38
+ * server or the CLI (for installing extensions, etc) but we patch it so we can
39
+ * `require` it and call its functions directly in order to integrate with our
40
+ * web server.
41
+ */
42
+ export type VSCodeModule = {
43
+ // See ../../../lib/vscode/src/server-main.js:339.
44
+ loadCodeWithNls ( ) : {
45
+ // See ../../../lib/vscode/src/vs/server/node/server.main.ts:72.
46
+ createServer ( address : string | net . AddressInfo | null , args : CodeArgs ) : Promise < IVSCodeServerAPI >
47
+ // See ../../../lib/vscode/src/vs/server/node/server.main.ts:65.
48
+ spawnCli ( args : CodeArgs ) : Promise < void >
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Load then create the VS Code server.
54
+ */
55
+ async function loadVSCode ( req : express . Request ) : Promise < IVSCodeServerAPI > {
56
+ const mod = require ( path . join ( vsRootPath , "out/server-main" ) ) as VSCodeModule
57
+ const serverModule = await mod . loadCodeWithNls ( )
58
+ return serverModule . createServer ( null , {
59
+ ...( await toCodeArgs ( req . args ) ) ,
60
+ "accept-server-license-terms" : true ,
61
+ // This seems to be used to make the connection token flags optional (when
62
+ // set to 1.63) but we have always included them.
63
+ compatibility : "1.64" ,
64
+ "without-connection-token" : true ,
65
+ } )
66
+ }
36
67
37
- // The VS Code server is dynamically loaded in when a request is made to this
38
- // router by `ensureCodeServerLoaded`.
68
+ // To prevent loading the module more than once at a time. We also have the
69
+ // resolved value so you do not need to `await` everywhere.
70
+ let vscodeServerPromise : Promise < IVSCodeServerAPI > | undefined
71
+
72
+ // The resolved value from the dynamically loaded VS Code server. Do not use
73
+ // without first calling and awaiting `ensureCodeServerLoaded`.
39
74
let vscodeServer : IVSCodeServerAPI | undefined
40
75
41
76
/**
@@ -49,21 +84,21 @@ export const ensureVSCodeLoaded = async (
49
84
if ( vscodeServer ) {
50
85
return next ( )
51
86
}
52
- // See ../../../lib/vscode/src/vs/server/node/server.main.ts:72.
53
- const createVSServer = await loadAMDModule < CreateServer > ( "vs/server/node/server.main" , "createServer" )
87
+ if ( ! vscodeServerPromise ) {
88
+ vscodeServerPromise = loadVSCode ( req )
89
+ }
54
90
try {
55
- vscodeServer = await createVSServer ( null , {
56
- ...( await toCodeArgs ( req . args ) ) ,
57
- "accept-server-license-terms" : true ,
58
- // This seems to be used to make the connection token flags optional (when
59
- // set to 1.63) but we have always included them.
60
- compatibility : "1.64" ,
61
- "without-connection-token" : true ,
62
- } )
91
+ vscodeServer = await vscodeServerPromise
63
92
} catch ( error ) {
93
+ vscodeServerPromise = undefined // Unset so we can try again.
64
94
logError ( logger , "CodeServerRouteWrapper" , error )
65
95
if ( isDevMode ) {
66
- return next ( new Error ( ( error instanceof Error ? error . message : error ) + " (VS Code may still be compiling)" ) )
96
+ return next (
97
+ new Error (
98
+ ( error instanceof Error ? error . message : error ) +
99
+ " (Have you applied the patches? If so, VS Code may still be compiling)" ,
100
+ ) ,
101
+ )
67
102
}
68
103
return next ( error )
69
104
}
0 commit comments