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