compiler.rs 5.0 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
use deno_core::ModuleLoader;
10
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
  let state_ = &state.borrow().global_state;
  let ts_compiler = state_.ts_compiler.clone();
47
  ts_compiler.cache_compiler_output(
48 49 50
    &module_specifier,
    &args.extension,
    &args.contents,
51
  )?;
B
Bartek Iwańczuk 已提交
52

B
Bartek Iwańczuk 已提交
53 54 55
  Ok(JsonOp::Sync(json!({})))
}

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

K
Kitson Kelly 已提交
62
fn op_resolve_modules(
63
  state: &State,
B
Bartek Iwańczuk 已提交
64
  args: Value,
R
Ryan Dahl 已提交
65
  _data: Option<ZeroCopyBuf>,
66
) -> Result<JsonOp, OpError> {
K
Kitson Kelly 已提交
67 68 69 70 71 72 73 74 75 76
  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 {
77 78 79 80
    let specifier = state
      .resolve(specifier, &referrer, is_main)
      .map_err(OpError::from)?;
    specifiers.push(specifier.as_str().to_owned());
K
Kitson Kelly 已提交
81 82 83 84 85 86
  }

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

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

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

101
  let global_state = state.borrow().global_state.clone();
102 103 104 105 106 107 108 109 110 111 112 113
  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_
114
            .fetch_source_file(&resolved_specifier, ref_specifier_)
115 116 117 118 119 120
            .await
        }
        .boxed_local()
      })
      .collect();

121
    let files = try_join_all(file_futures).await.map_err(OpError::from)?;
122
    // We want to get an array of futures that resolves to
123
    let v = files.into_iter().map(|f| {
124
      async {
125 126 127 128 129 130 131
        // 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
132
              .fetch_source_file(&types_specifier, ref_specifier.clone())
133 134
              .await
              .map_err(OpError::from)?
135 136 137
          }
          _ => f,
        };
138
        // Special handling of WASM and JSON files:
139
        // compile them into JS first!
140
        // This allows TS to do correct export types as well as bundles.
141 142 143 144
        let source_code = match file.media_type {
          msg::MediaType::Wasm => {
            global_state
              .wasm_compiler
145
              .compile(global_state.clone(), &file)
146 147
              .await
              .map_err(|e| OpError::other(e.to_string()))?
148
              .code
149
          }
150 151 152 153 154 155 156 157
          msg::MediaType::Json => {
            global_state
              .json_compiler
              .compile(&file)
              .await
              .map_err(|e| OpError::other(e.to_string()))?
              .code
          }
158 159
          _ => String::from_utf8(file.source_code)
            .map_err(|_| OpError::invalid_utf8())?,
160
        };
161
        Ok::<_, OpError>(json!({
162 163 164 165 166 167
          "url": file.url.to_string(),
          "filename": file.filename.to_str().unwrap(),
          "mediaType": file.media_type as i32,
          "sourceCode": source_code,
        }))
      }
K
Kitson Kelly 已提交
168
    });
169

170 171
    let v = try_join_all(v).await?;
    Ok(v.into())
172 173
  }
  .boxed_local();
174 175

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