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