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