Create an old program to be used in snapshot. (#3644)

This commit is contained in:
Kitson Kelly 2020-01-12 22:20:33 +11:00 committed by Bartek Iwańczuk
parent 8fac8ab130
commit 737ab94ea1
14 changed files with 85 additions and 60 deletions

View file

@ -6,6 +6,7 @@ import "./globals.ts";
import "./ts_global.d.ts";
import { TranspileOnlyResult } from "./compiler_api.ts";
import { oldProgram } from "./compiler_bootstrap.ts";
import { setRootExports } from "./compiler_bundler.ts";
import {
defaultBundlerOptions,
@ -73,7 +74,7 @@ interface CompileResult {
// bootstrap the runtime environment, this gets called as the isolate is setup
self.denoMain = function denoMain(compilerType?: string): void {
os.start(true, compilerType || "TS");
os.start(true, compilerType ?? "TS");
};
// bootstrap the worker environment, this gets called as the isolate is setup
@ -135,7 +136,12 @@ self.compilerMain = function compilerMain(): void {
// to generate the program and possibly emit it.
if (!diagnostics || (diagnostics && diagnostics.length === 0)) {
const options = host.getCompilationSettings();
const program = ts.createProgram(rootNames, options, host);
const program = ts.createProgram({
rootNames,
options,
host,
oldProgram
});
diagnostics = ts
.getPreEmitDiagnostics(program)
@ -213,11 +219,12 @@ self.compilerMain = function compilerMain(): void {
}
host.mergeOptions(...compilerOptions);
const program = ts.createProgram(
const program = ts.createProgram({
rootNames,
host.getCompilationSettings(),
host
);
options: host.getCompilationSettings(),
host,
oldProgram
});
if (bundle) {
setRootExports(program, rootNames[0]);

View file

@ -0,0 +1,34 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { ASSETS, Host } from "./compiler_host.ts";
import { core } from "./core.ts";
import * as dispatch from "./dispatch.ts";
import { sendSync } from "./dispatch_json.ts";
// This registers ops that are available during the snapshotting process.
const ops = core.ops();
for (const [name, opId] of Object.entries(ops)) {
const opName = `OP_${name.toUpperCase()}`;
// TODO This type casting is dangerous, and should be improved when the same
// code in `os.ts` is done.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(dispatch as any)[opName] = opId;
}
const host = new Host({ writeFile(): void {} });
const options = host.getCompilationSettings();
/** Used to generate the foundational AST for all other compilations, so it can
* be cached as part of the snapshot and available to speed up startup */
export const oldProgram = ts.createProgram({
rootNames: [`${ASSETS}/bootstrap.ts`],
options,
host
});
/** A module loader which is concatenated into bundle files. We read all static
* assets during the snapshotting process, which is why this is located in
* compiler_bootstrap. */
export const bundleLoader = sendSync(dispatch.OP_FETCH_ASSET, {
name: "bundle_loader.js"
});

View file

@ -1,7 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as dispatch from "./dispatch.ts";
import { sendSync } from "./dispatch_json.ts";
import { bundleLoader } from "./compiler_bootstrap.ts";
import {
assert,
commonPath,
@ -9,11 +8,6 @@ import {
CHAR_FORWARD_SLASH
} from "./util.ts";
const BUNDLE_LOADER = "bundle_loader.js";
/** A loader of bundled modules that we will inline into any bundle outputs. */
let bundleLoader: string;
/** Local state of what the root exports are of a root module. */
let rootExports: string[] | undefined;
@ -40,12 +34,6 @@ export function buildBundle(
data: string,
sourceFiles: readonly ts.SourceFile[]
): string {
// we can only do this once we are bootstrapped and easiest way to do it is
// inline here
if (!bundleLoader) {
bundleLoader = sendSync(dispatch.OP_FETCH_ASSET, { name: BUNDLE_LOADER });
}
// when outputting to AMD and a single outfile, TypeScript makes up the module
// specifiers which are used to define the modules, and doesn't expose them
// publicly, so we have to try to replicate

View file

@ -18,7 +18,7 @@ export interface ConfigureResponse {
diagnostics?: ts.Diagnostic[];
}
const ASSETS = "$asset$";
export const ASSETS = "$asset$";
/** Options that need to be used when generating a bundle (either trusted or
* runtime). */
@ -129,11 +129,11 @@ export class Host implements ts.CompilerHost {
private _writeFile: WriteFileCallback;
private _getAsset(filename: string): SourceFile {
const sourceFile = SourceFile.get(filename);
const url = filename.split("/").pop()!;
const sourceFile = SourceFile.get(url);
if (sourceFile) {
return sourceFile;
}
const url = filename.split("/").pop()!;
const name = url.includes(".") ? url : `${url}.d.ts`;
const sourceCode = sendSync(dispatch.OP_FETCH_ASSET, { name });
return new SourceFile({
@ -238,13 +238,15 @@ export class Host implements ts.CompilerHost {
: SourceFile.get(fileName);
assert(sourceFile != null);
if (!sourceFile.tsSourceFile) {
assert(sourceFile.sourceCode != null);
sourceFile.tsSourceFile = ts.createSourceFile(
fileName,
sourceFile.sourceCode,
languageVersion
);
delete sourceFile.sourceCode;
}
return sourceFile!.tsSourceFile;
return sourceFile.tsSourceFile;
} catch (e) {
if (onError) {
onError(String(e));

View file

@ -61,7 +61,7 @@ export class SourceFile {
mediaType!: MediaType;
processed = false;
sourceCode!: string;
sourceCode?: string;
tsSourceFile?: ts.SourceFile;
url!: string;

View file

@ -66,13 +66,16 @@ export let OP_READ_LINK: number;
export let OP_TRUNCATE: number;
export let OP_MAKE_TEMP_DIR: number;
export let OP_CWD: number;
export let OP_FETCH_ASSET: number;
export let OP_DIAL_TLS: number;
export let OP_HOSTNAME: number;
export let OP_OPEN_PLUGIN: number;
export let OP_COMPILE: number;
export let OP_TRANSPILE: number;
/** **WARNING:** This is only available during the snapshotting process and is
* unavailable at runtime. */
export let OP_FETCH_ASSET: number;
const PLUGIN_ASYNC_HANDLER_MAP: Map<number, AsyncHandler> = new Map();
export function setPluginAsyncHandler(

View file

@ -62,7 +62,7 @@ export function sendSync(
const resUi8 = core.dispatch(opId, argsUi8, zeroCopy);
util.assert(resUi8 != null);
const res = decode(resUi8!);
const res = decode(resUi8);
util.assert(res.promiseId == null);
return unwrapResponse(res);
}