compiler.rs 4.8 KB
Newer Older
R
Ry Dahl 已提交
1
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
2 3 4
use super::dispatch_json::Deserialize;
use super::dispatch_json::JsonOp;
use super::dispatch_json::Value;
B
Bartek Iwańczuk 已提交
5
use crate::futures::future::try_join_all;
6
use crate::msg;
7
use crate::op_error::OpError;
8
use crate::state::State;
9 10
use deno_core::Loader;
use deno_core::*;
11
use futures::future::FutureExt;
B
Bartek Iwańczuk 已提交
12

13
pub fn init(i: &mut Isolate, s: &State) {
R
Ryan Dahl 已提交
14 15
  i.register_op("op_cache", s.stateful_json_op(op_cache));
  i.register_op("op_resolve_modules", s.stateful_json_op(op_resolve_modules));
K
Kitson Kelly 已提交
16
  i.register_op(
R
Ryan Dahl 已提交
17 18
    "op_fetch_source_files",
    s.stateful_json_op(op_fetch_source_files),
K
Kitson Kelly 已提交
19
  );
R
Ryan Dahl 已提交
20
  let custom_assets = std::collections::HashMap::new(); // TODO(ry) use None.
21
  i.register_op(
R
Ryan Dahl 已提交
22 23
    "op_fetch_asset",
    deno_typescript::op_fetch_asset(custom_assets),
24
  );
25 26
}

B
Bartek Iwańczuk 已提交
27 28 29 30 31 32 33
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CacheArgs {
  module_id: String,
  contents: String,
  extension: String,
}
B
Bartek Iwańczuk 已提交
34

35
fn op_cache(
36
  state: &State,
B
Bartek Iwańczuk 已提交
37
  args: Value,
R
Ryan Dahl 已提交
38
  _zero_copy: Option<ZeroCopyBuf>,
39
) -> Result<JsonOp, OpError> {
B
Bartek Iwańczuk 已提交
40
  let args: CacheArgs = serde_json::from_value(args)?;
B
Bartek Iwańczuk 已提交
41

B
Bartek Iwańczuk 已提交
42
  let module_specifier = ModuleSpecifier::resolve_url(&args.module_id)
B
Bartek Iwańczuk 已提交
43 44
    .expect("Should be valid module specifier");

45 46 47 48 49 50 51
  let state_ = &state.borrow().global_state;
  let ts_compiler = state_.ts_compiler.clone();
  let fut = ts_compiler.cache_compiler_output(
    &module_specifier,
    &args.extension,
    &args.contents,
  );
B
Bartek Iwańczuk 已提交
52

53
  futures::executor::block_on(fut)?;
B
Bartek Iwańczuk 已提交
54 55 56
  Ok(JsonOp::Sync(json!({})))
}

K
Kitson Kelly 已提交
57 58
#[derive(Deserialize, Debug)]
struct SpecifiersReferrerArgs {
59
  specifiers: Vec<String>,
60
  referrer: Option<String>,
B
Bartek Iwańczuk 已提交
61 62
}

K
Kitson Kelly 已提交
63
fn op_resolve_modules(
64
  state: &State,
B
Bartek Iwańczuk 已提交
65
  args: Value,
R
Ryan Dahl 已提交
66
  _data: Option<ZeroCopyBuf>,
67
) -> Result<JsonOp, OpError> {
K
Kitson Kelly 已提交
68 69 70 71 72 73 74 75 76 77
  let args: SpecifiersReferrerArgs = serde_json::from_value(args)?;
  let (referrer, is_main) = if let Some(referrer) = args.referrer {
    (referrer, false)
  } else {
    ("<unknown>".to_owned(), true)
  };

  let mut specifiers = vec![];

  for specifier in &args.specifiers {
78 79 80 81
    let specifier = state
      .resolve(specifier, &referrer, is_main)
      .map_err(OpError::from)?;
    specifiers.push(specifier.as_str().to_owned());
K
Kitson Kelly 已提交
82 83 84 85 86 87
  }

  Ok(JsonOp::Sync(json!(specifiers)))
}

fn op_fetch_source_files(
88
  state: &State,
K
Kitson Kelly 已提交
89
  args: Value,
R
Ryan Dahl 已提交
90
  _data: Option<ZeroCopyBuf>,
91
) -> Result<JsonOp, OpError> {
K
Kitson Kelly 已提交
92 93 94
  let args: SpecifiersReferrerArgs = serde_json::from_value(args)?;

  let ref_specifier = if let Some(referrer) = args.referrer {
95 96
    let specifier = ModuleSpecifier::resolve_url(&referrer)
      .expect("Referrer is not a valid specifier");
K
Kitson Kelly 已提交
97
    Some(specifier)
98
  } else {
K
Kitson Kelly 已提交
99
    None
100 101
  };

102
  let global_state = state.borrow().global_state.clone();
103 104 105 106 107 108 109 110 111 112 113 114
  let file_fetcher = global_state.file_fetcher.clone();
  let specifiers = args.specifiers.clone();
  let future = async move {
    let file_futures: Vec<_> = specifiers
      .into_iter()
      .map(|specifier| {
        let file_fetcher_ = file_fetcher.clone();
        let ref_specifier_ = ref_specifier.clone();
        async move {
          let resolved_specifier = ModuleSpecifier::resolve_url(&specifier)
            .expect("Invalid specifier");
          file_fetcher_
115
            .fetch_source_file(&resolved_specifier, ref_specifier_)
116 117 118 119 120 121
            .await
        }
        .boxed_local()
      })
      .collect();

122
    let files = try_join_all(file_futures).await.map_err(OpError::from)?;
123
    // We want to get an array of futures that resolves to
124
    let v = files.into_iter().map(|f| {
125
      async {
126 127 128 129 130 131 132
        // if the source file contains a `types_url` we need to replace
        // the module with the type definition when requested by the compiler
        let file = match f.types_url {
          Some(types_url) => {
            let types_specifier = ModuleSpecifier::from(types_url);
            global_state
              .file_fetcher
133
              .fetch_source_file(&types_specifier, ref_specifier.clone())
134 135
              .await
              .map_err(OpError::from)?
136 137 138
          }
          _ => f,
        };
139 140 141 142 143 144 145
        // Special handling of Wasm files:
        // compile them into JS first!
        // This allows TS to do correct export types.
        let source_code = match file.media_type {
          msg::MediaType::Wasm => {
            global_state
              .wasm_compiler
146
              .compile(global_state.clone(), &file)
147 148
              .await
              .map_err(|e| OpError::other(e.to_string()))?
149
              .code
150
          }
151 152
          _ => String::from_utf8(file.source_code).unwrap(),
        };
153
        Ok::<_, OpError>(json!({
154 155 156 157 158 159
          "url": file.url.to_string(),
          "filename": file.filename.to_str().unwrap(),
          "mediaType": file.media_type as i32,
          "sourceCode": source_code,
        }))
      }
K
Kitson Kelly 已提交
160
    });
161

162 163
    let v = try_join_all(v).await?;
    Ok(v.into())
164 165
  }
  .boxed_local();
166 167

  Ok(JsonOp::Async(future))
B
Bartek Iwańczuk 已提交
168
}