1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-12 02:27:46 -05:00
denoland-deno/cli/ops/compiler.rs
Kitson Kelly d9ff4eccb5 Async compiler processing (#3043)
Basically this does pre-processing of TypeScript files and gathers all the
dependencies asynchronously. Only then after all the dependencies are gathered,
does it do a compile, which at that point all the dependencies are cached in
memory in the compiler, so with the exception of the hard coded assets, there
are no ops during the compilation.

Because op_fetch_source_files is now handled asynchronously in the runtime, we
can eliminate the tokio_util::block_on() which was causing the increase in
threads. Benchmarking on my machine has shown about a 5% improvement in speed
when dealing with compiling TypeScript. Still a long way to go, but an
improvement.

In theory the module name resolution and the fetching of the source files could
be broken out as two different ops. This would prevent situations of sending the
full source file all the time when actually the module is the same module
referenced by multiple modules, but that could be done subsequently to this.
2019-10-03 07:23:29 -04:00

99 lines
2.5 KiB
Rust

// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::futures::future::join_all;
use crate::futures::Future;
use crate::state::ThreadSafeState;
use deno::*;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CacheArgs {
module_id: String,
contents: String,
extension: String,
}
pub fn op_cache(
state: &ThreadSafeState,
args: Value,
_zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> {
let args: CacheArgs = serde_json::from_value(args)?;
let module_specifier = ModuleSpecifier::resolve_url(&args.module_id)
.expect("Should be valid module specifier");
state.ts_compiler.cache_compiler_output(
&module_specifier,
&args.extension,
&args.contents,
)?;
Ok(JsonOp::Sync(json!({})))
}
#[derive(Deserialize)]
struct FetchSourceFilesArgs {
specifiers: Vec<String>,
referrer: String,
}
pub fn op_fetch_source_files(
state: &ThreadSafeState,
args: Value,
_data: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> {
let args: FetchSourceFilesArgs = serde_json::from_value(args)?;
// TODO(ry) Maybe a security hole. Only the compiler worker should have access
// to this. Need a test to demonstrate the hole.
let is_dyn_import = false;
let mut futures = vec![];
for specifier in &args.specifiers {
let resolved_specifier =
state.resolve(specifier, &args.referrer, false, is_dyn_import)?;
let fut = state
.file_fetcher
.fetch_source_file_async(&resolved_specifier);
futures.push(fut);
}
let future = join_all(futures)
.map_err(ErrBox::from)
.and_then(move |files| {
let res = files
.into_iter()
.map(|file| {
json!({
"url": file.url.to_string(),
"filename": file.filename.to_str().unwrap(),
"mediaType": file.media_type as i32,
"sourceCode": String::from_utf8(file.source_code).unwrap(),
})
})
.collect();
futures::future::ok(res)
});
Ok(JsonOp::Async(Box::new(future)))
}
#[derive(Deserialize)]
struct FetchAssetArgs {
name: String,
}
pub fn op_fetch_asset(
_state: &ThreadSafeState,
args: Value,
_zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> {
let args: FetchAssetArgs = serde_json::from_value(args)?;
if let Some(source_code) = deno_cli_snapshots::get_asset(&args.name) {
Ok(JsonOp::Sync(json!(source_code)))
} else {
panic!("op_fetch_asset bad asset {}", args.name)
}
}