1/*@internal*/ 2namespace ts.server { 3 declare const addEventListener: any; 4 declare const postMessage: any; 5 declare const close: any; 6 declare const location: any; 7 declare const XMLHttpRequest: any; 8 declare const self: any; 9 10 const nullLogger: Logger = { 11 close: noop, 12 hasLevel: returnFalse, 13 loggingEnabled: returnFalse, 14 perftrc: noop, 15 info: noop, 16 msg: noop, 17 startGroup: noop, 18 endGroup: noop, 19 getLogFileName: returnUndefined, 20 }; 21 22 function parseServerMode(): LanguageServiceMode | string | undefined { 23 const mode = findArgument("--serverMode"); 24 if (!mode) return undefined; 25 switch (mode.toLowerCase()) { 26 case "partialsemantic": 27 return LanguageServiceMode.PartialSemantic; 28 case "syntactic": 29 return LanguageServiceMode.Syntactic; 30 default: 31 return mode; 32 } 33 } 34 35 export function initializeWebSystem(args: string[]): StartInput { 36 createWebSystem(args); 37 const modeOrUnknown = parseServerMode(); 38 let serverMode: LanguageServiceMode | undefined; 39 let unknownServerMode: string | undefined; 40 if (typeof modeOrUnknown === "number") serverMode = modeOrUnknown; 41 else unknownServerMode = modeOrUnknown; 42 return { 43 args, 44 logger: createLogger(), 45 cancellationToken: nullCancellationToken, 46 // Webserver defaults to partial semantic mode 47 serverMode: serverMode ?? LanguageServiceMode.PartialSemantic, 48 unknownServerMode, 49 startSession: startWebSession 50 }; 51 } 52 53 function createLogger() { 54 const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); 55 return cmdLineVerbosity !== undefined ? new MainProcessLogger(cmdLineVerbosity, { writeMessage }) : nullLogger; 56 } 57 58 function writeMessage(s: any) { 59 postMessage(s); 60 } 61 62 function createWebSystem(args: string[]) { 63 Debug.assert(ts.sys === undefined); 64 const webHost: WebHost = { 65 readFile: webPath => { 66 const request = new XMLHttpRequest(); 67 request.open("GET", webPath, /* asynchronous */ false); 68 request.send(); 69 return request.status === 200 ? request.responseText : undefined; 70 }, 71 fileExists: webPath => { 72 const request = new XMLHttpRequest(); 73 request.open("HEAD", webPath, /* asynchronous */ false); 74 request.send(); 75 return request.status === 200; 76 }, 77 writeMessage, 78 }; 79 // Do this after sys has been set as findArguments is going to work only then 80 const sys = server.createWebSystem(webHost, args, () => findArgument("--executingFilePath") || location + ""); 81 ts.sys = sys; 82 const localeStr = findArgument("--locale"); 83 if (localeStr) { 84 validateLocaleAndSetLanguage(localeStr, sys); 85 } 86 } 87 88 function hrtime(previous?: [number, number]) { 89 const now = self.performance.now(performance) * 1e-3; 90 let seconds = Math.floor(now); 91 let nanoseconds = Math.floor((now % 1) * 1e9); 92 if (previous) { 93 seconds = seconds - previous[0]; 94 nanoseconds = nanoseconds - previous[1]; 95 if (nanoseconds < 0) { 96 seconds--; 97 nanoseconds += 1e9; 98 } 99 } 100 return [seconds, nanoseconds]; 101 } 102 103 function startWebSession(options: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken) { 104 class WorkerSession extends server.WorkerSession { 105 constructor() { 106 super(sys as ServerHost, { writeMessage }, options, logger, cancellationToken, hrtime); 107 } 108 109 exit() { 110 this.logger.info("Exiting..."); 111 this.projectService.closeLog(); 112 close(0); 113 } 114 115 listen() { 116 addEventListener("message", (message: any) => { 117 this.onMessage(message.data); 118 }); 119 } 120 } 121 122 const session = new WorkerSession(); 123 124 // Start listening 125 session.listen(); 126 } 127} 128