-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Adds experimental support for running TS Server in a web worker #39656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
e50aedc
Adds experimental support for running TS Server in a web worker
mjbvz 30cb1a6
Shim out directoryExists
mjbvz fb900a0
Add some regions
mjbvz 4ce8d4a
Remove some inlined note types
mjbvz 94faf66
Use switch case for runtime
mjbvz f6c0749
Merge branch 'master' into web-worker-server
sheetalkamat f3178b6
Review and updates
sheetalkamat 6202c51
Enable loading std library d.ts files
mjbvz b6e8137
Update src/tsserver/webServer.ts
sheetalkamat dd331e2
Update src/tsserver/webServer.ts
mjbvz 2d4c726
Addressing feedback
mjbvz 69a6523
Allow passing in explicit executingFilePath
mjbvz 5185f6e
Adding logging support
mjbvz 1db3ebc
Do not create auto import provider in partial semantic mode
sheetalkamat 9a1eace
Handle lib files by doing path mapping instead
sheetalkamat c92d22d
Merge branch 'master' into web-worker-server
sheetalkamat 14498b8
Merge branch 'master' into web-worker-server
sheetalkamat 04a4fe7
TODO
sheetalkamat b959f3e
Add log message
mjbvz 2359c83
Move code around so that exported functions are set on namespace
sheetalkamat f29b2e7
Log response
sheetalkamat 0edf650
Map the paths back to https:
sheetalkamat 0820519
If files are not open dont schedule open file project ensure
sheetalkamat 7e49390
Should also check if there are no external projects before skipping s…
sheetalkamat 16ff1ce
Revert "Map the paths back to https:"
sheetalkamat 9952bab
Revert "TODO"
sheetalkamat 2bf35c9
Revert "Should also check if there are no external projects before sk…
sheetalkamat 3c94c98
Merge branch 'master' into web-worker-server
sheetalkamat 542a8b0
Refactoring so we can test the changes out
sheetalkamat 245e49d
Feedback
sheetalkamat 9704738
Merge branch 'master' into web-worker-server
sheetalkamat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
namespace ts.projectSystem { | ||
describe("unittests:: tsserver:: webServer", () => { | ||
class TestWorkerSession extends server.WorkerSession { | ||
constructor(host: server.ServerHost, webHost: server.HostWithWriteMessage, options: Partial<server.StartSessionOptions>, logger: server.Logger) { | ||
super( | ||
host, | ||
webHost, | ||
{ | ||
globalPlugins: undefined, | ||
pluginProbeLocations: undefined, | ||
allowLocalPluginLoads: undefined, | ||
useSingleInferredProject: true, | ||
useInferredProjectPerProjectRoot: false, | ||
suppressDiagnosticEvents: false, | ||
noGetErrOnBackgroundUpdate: true, | ||
syntaxOnly: undefined, | ||
serverMode: undefined, | ||
...options | ||
}, | ||
logger, | ||
server.nullCancellationToken, | ||
() => emptyArray | ||
); | ||
} | ||
|
||
getProjectService() { | ||
return this.projectService; | ||
} | ||
} | ||
function setup(logLevel: server.LogLevel | undefined) { | ||
const host = createServerHost([libFile], { windowsStyleRoot: "c:/" }); | ||
const messages: any[] = []; | ||
const webHost: server.WebHost = { | ||
readFile: s => host.readFile(s), | ||
fileExists: s => host.fileExists(s), | ||
writeMessage: s => messages.push(s), | ||
}; | ||
const webSys = server.createWebSystem(webHost, emptyArray, () => host.getExecutingFilePath()); | ||
const logger = logLevel !== undefined ? new server.MainProcessLogger(logLevel, webHost) : nullLogger; | ||
const session = new TestWorkerSession(webSys, webHost, { serverMode: LanguageServiceMode.PartialSemantic }, logger); | ||
return { getMessages: () => messages, clearMessages: () => messages.length = 0, session }; | ||
|
||
} | ||
|
||
describe("open files are added to inferred project and semantic operations succeed", () => { | ||
function verify(logLevel: server.LogLevel | undefined) { | ||
const { session, clearMessages, getMessages } = setup(logLevel); | ||
const service = session.getProjectService(); | ||
const file: File = { | ||
path: "^memfs:/sample-folder/large.ts", | ||
content: "export const numberConst = 10; export const arrayConst: Array<string> = [];" | ||
}; | ||
session.executeCommand({ | ||
seq: 1, | ||
type: "request", | ||
command: protocol.CommandTypes.Open, | ||
arguments: { | ||
file: file.path, | ||
fileContent: file.content | ||
} | ||
}); | ||
checkNumberOfProjects(service, { inferredProjects: 1 }); | ||
const project = service.inferredProjects[0]; | ||
checkProjectActualFiles(project, ["/lib.d.ts", file.path]); // Lib files are rooted | ||
verifyQuickInfo(); | ||
verifyGotoDefInLib(); | ||
|
||
function verifyQuickInfo() { | ||
clearMessages(); | ||
const start = protocolFileLocationFromSubstring(file, "numberConst"); | ||
session.onMessage({ | ||
seq: 2, | ||
type: "request", | ||
command: protocol.CommandTypes.Quickinfo, | ||
arguments: start | ||
}); | ||
assert.deepEqual(last(getMessages()), { | ||
seq: 0, | ||
type: "response", | ||
command: protocol.CommandTypes.Quickinfo, | ||
request_seq: 2, | ||
success: true, | ||
performanceData: undefined, | ||
body: { | ||
kind: ScriptElementKind.constElement, | ||
kindModifiers: "export", | ||
start: { line: start.line, offset: start.offset }, | ||
end: { line: start.line, offset: start.offset + "numberConst".length }, | ||
displayString: "const numberConst: 10", | ||
documentation: "", | ||
tags: [] | ||
} | ||
}); | ||
verifyLogger(); | ||
} | ||
|
||
function verifyGotoDefInLib() { | ||
clearMessages(); | ||
const start = protocolFileLocationFromSubstring(file, "Array"); | ||
session.onMessage({ | ||
seq: 3, | ||
type: "request", | ||
command: protocol.CommandTypes.DefinitionAndBoundSpan, | ||
arguments: start | ||
}); | ||
assert.deepEqual(last(getMessages()), { | ||
seq: 0, | ||
type: "response", | ||
command: protocol.CommandTypes.DefinitionAndBoundSpan, | ||
request_seq: 3, | ||
success: true, | ||
performanceData: undefined, | ||
body: { | ||
definitions: [{ | ||
file: "/lib.d.ts", | ||
...protocolTextSpanWithContextFromSubstring({ | ||
fileText: libFile.content, | ||
text: "Array", | ||
contextText: "interface Array<T> { length: number; [n: number]: T; }" | ||
}) | ||
}], | ||
textSpan: { | ||
start: { line: start.line, offset: start.offset }, | ||
end: { line: start.line, offset: start.offset + "Array".length }, | ||
} | ||
} | ||
}); | ||
verifyLogger(); | ||
} | ||
|
||
function verifyLogger() { | ||
const messages = getMessages(); | ||
assert.equal(messages.length, logLevel === server.LogLevel.verbose ? 4 : 1, `Expected ${JSON.stringify(messages)}`); | ||
if (logLevel === server.LogLevel.verbose) { | ||
verifyLogMessages(messages[0], "info"); | ||
verifyLogMessages(messages[1], "perf"); | ||
verifyLogMessages(messages[2], "info"); | ||
} | ||
clearMessages(); | ||
} | ||
|
||
function verifyLogMessages(actual: any, expectedLevel: server.MessageLogLevel) { | ||
assert.equal(actual.type, "log"); | ||
assert.equal(actual.level, expectedLevel); | ||
} | ||
} | ||
|
||
it("with logging enabled", () => { | ||
verify(server.LogLevel.verbose); | ||
}); | ||
|
||
it("with logging disabled", () => { | ||
verify(/*logLevel*/ undefined); | ||
}); | ||
}); | ||
}); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.