refactor: cleanup compiler runtimes (#4230)

- Cleanup "tsCompilerOnMessage" by factoring out separate methods for each 
  request type:
    * "compile"
    * "runtimeCompile"
    * "runtimeTranspile"
- Simplify control flow of compiler workers by a) no longer calling "close()" in worker runtime after a
single message; b) explicitly shutting down worker from host after a single message

Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
This commit is contained in:
Bartek Iwańczuk 2020-03-05 11:13:10 +01:00 committed by GitHub
parent 159de0245d
commit 52b96fc22a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 270 additions and 253 deletions

View file

@ -620,11 +620,7 @@ async fn execute_in_thread(
WorkerEvent::Message(buf) => Ok(buf),
WorkerEvent::Error(error) => Err(error),
}?;
// Compiler worker finishes after one request
// so we should receive signal that channel was closed.
// Then close worker's channel and join the thread.
let event = handle.get_event().await;
assert!(event.is_none());
// Shutdown worker and wait for thread to finish
handle.sender.close_channel();
join_handle.join().unwrap();
Ok(buf)

View file

@ -134,11 +134,7 @@ async fn execute_in_thread(
WorkerEvent::Message(buf) => Ok(buf),
WorkerEvent::Error(error) => Err(error),
}?;
// Compiler worker finishes after one request
// so we should receive signal that channel was closed.
// Then close worker's channel and join the thread.
let event = handle.get_event().await;
assert!(event.is_none());
// Shutdown worker and wait for thread to finish
handle.sender.close_channel();
join_handle.join().unwrap();
Ok(buf)

View file

@ -36,7 +36,7 @@ import {
WriteFileState,
processConfigureResponse
} from "./compiler_util.ts";
import { Diagnostic } from "./diagnostics.ts";
import { Diagnostic, DiagnosticItem } from "./diagnostics.ts";
import { fromTypeScriptDiagnostic } from "./diagnostics_util.ts";
import { assert } from "./util.ts";
import * as util from "./util.ts";
@ -81,25 +81,19 @@ interface CompileResult {
diagnostics?: Diagnostic;
}
// TODO(bartlomieju): refactor this function into multiple functions
// per CompilerRequestType
async function tsCompilerOnMessage({
data: request
}: {
data: CompilerRequest;
}): Promise<void> {
switch (request.type) {
// `Compile` are requests from the internals to Deno, generated by both
// the `run` and `bundle` sub command.
case CompilerRequestType.Compile: {
const {
bundle,
config,
configPath,
outFile,
rootNames,
target
} = request;
type RuntimeCompileResult = [
undefined | DiagnosticItem[],
Record<string, string>
];
type RuntimeBundleResult = [undefined | DiagnosticItem[], string];
/** `Compile` are requests from the internals of Deno; eg. used when
* the `run` or `bundle` subcommand is used. */
async function compile(
request: CompilerRequestCompile
): Promise<CompileResult> {
const { bundle, config, configPath, outFile, rootNames, target } = request;
util.log(">>> compile start", {
rootNames,
type: CompilerRequestType[request.type]
@ -182,18 +176,26 @@ async function tsCompilerOnMessage({
? fromTypeScriptDiagnostic(diagnostics)
: undefined
};
globalThis.postMessage(result);
util.log("<<< compile end", {
rootNames,
type: CompilerRequestType[request.type]
});
break;
}
case CompilerRequestType.RuntimeCompile: {
// `RuntimeCompile` are requests from a runtime user, both compiles and
// bundles. The process is similar to a request from the privileged
// side, but also returns the output to the on message.
return result;
}
/**`RuntimeCompile` are requests from a runtime user; it can be both
* "compile" and "bundle".
*
* The process is similar to a request from the privileged
* side, but unline `compile`, `runtimeCompile` allows to specify
* additional file mappings which can be used instead of relying
* on Deno defaults.
*/
async function runtimeCompile(
request: CompilerRequestRuntimeCompile
): Promise<RuntimeCompileResult | RuntimeBundleResult> {
const { rootName, sources, options, bundle, target } = request;
util.log(">>> runtime compile start", {
@ -204,9 +206,7 @@ async function tsCompilerOnMessage({
// resolve the root name, if there are sources, the root name does not
// get resolved
const resolvedRootName = sources
? rootName
: resolveModules([rootName])[0];
const resolvedRootName = sources ? rootName : resolveModules([rootName])[0];
// if there are options, convert them into TypeScript compiler options,
// and resolve any external file references
@ -293,13 +293,6 @@ async function tsCompilerOnMessage({
const emitResult = program.emit();
assert(emitResult.emitSkipped === false, "Unexpected skip of the emit.");
const result = [
diagnostics.length
? fromTypeScriptDiagnostic(diagnostics).items
: undefined,
bundle ? state.emitBundle : state.emitMap
];
globalThis.postMessage(result);
assert(state.emitMap);
util.log("<<< runtime compile finish", {
@ -309,9 +302,20 @@ async function tsCompilerOnMessage({
emitMap: Object.keys(state.emitMap)
});
break;
const maybeDiagnostics = diagnostics.length
? fromTypeScriptDiagnostic(diagnostics).items
: undefined;
if (bundle) {
return [maybeDiagnostics, state.emitBundle] as RuntimeBundleResult;
} else {
return [maybeDiagnostics, state.emitMap] as RuntimeCompileResult;
}
case CompilerRequestType.RuntimeTranspile: {
}
async function runtimeTranspile(
request: CompilerRequestRuntimeTranspile
): Promise<Record<string, TranspileOnlyResult>> {
const result: Record<string, TranspileOnlyResult> = {};
const { sources, options } = request;
const compilerOptions = options
@ -332,8 +336,32 @@ async function tsCompilerOnMessage({
);
result[fileName] = { source, map };
}
globalThis.postMessage(result);
return result;
}
async function tsCompilerOnMessage({
data: request
}: {
data: CompilerRequest;
}): Promise<void> {
switch (request.type) {
case CompilerRequestType.Compile: {
const result = await compile(request as CompilerRequestCompile);
globalThis.postMessage(result);
break;
}
case CompilerRequestType.RuntimeCompile: {
const result = await runtimeCompile(
request as CompilerRequestRuntimeCompile
);
globalThis.postMessage(result);
break;
}
case CompilerRequestType.RuntimeTranspile: {
const result = await runtimeTranspile(
request as CompilerRequestRuntimeTranspile
);
globalThis.postMessage(result);
break;
}
default:
@ -343,9 +371,7 @@ async function tsCompilerOnMessage({
} (${CompilerRequestType[(request as CompilerRequest).type]})`
);
}
// The compiler isolate exits after a single message.
globalThis.close();
// Currently Rust shuts down worker after single request
}
async function wasmCompilerOnMessage({
@ -372,8 +398,7 @@ async function wasmCompilerOnMessage({
util.log("<<< WASM compile end");
// The compiler isolate exits after a single message.
globalThis.close();
// Currently Rust shuts down worker after single request
}
function bootstrapTsCompilerRuntime(): void {