• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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