compiler.rs 4.2 KB
Newer Older
R
Ry Dahl 已提交
1
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
B
Bartek Iwańczuk 已提交
2
use super::dispatch_json::{Deserialize, JsonOp, Value};
B
Bartek Iwańczuk 已提交
3
use crate::futures::future::try_join_all;
4
use crate::msg;
5
use crate::ops::json_op;
B
Bartek Iwańczuk 已提交
6
use crate::state::ThreadSafeState;
7 8
use deno_core::Loader;
use deno_core::*;
B
Bartek Iwańczuk 已提交
9

10 11
pub fn init(i: &mut Isolate, s: &ThreadSafeState) {
  i.register_op("cache", s.core_op(json_op(s.stateful_op(op_cache))));
K
Kitson Kelly 已提交
12 13 14 15
  i.register_op(
    "resolve_modules",
    s.core_op(json_op(s.stateful_op(op_resolve_modules))),
  );
16 17 18 19 20 21
  i.register_op(
    "fetch_source_files",
    s.core_op(json_op(s.stateful_op(op_fetch_source_files))),
  );
}

B
Bartek Iwańczuk 已提交
22 23 24 25 26 27 28
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CacheArgs {
  module_id: String,
  contents: String,
  extension: String,
}
B
Bartek Iwańczuk 已提交
29

30
fn op_cache(
B
Bartek Iwańczuk 已提交
31
  state: &ThreadSafeState,
B
Bartek Iwańczuk 已提交
32
  args: Value,
R
Ryan Dahl 已提交
33
  _zero_copy: Option<ZeroCopyBuf>,
B
Bartek Iwańczuk 已提交
34 35
) -> Result<JsonOp, ErrBox> {
  let args: CacheArgs = serde_json::from_value(args)?;
B
Bartek Iwańczuk 已提交
36

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

40
  state.global_state.ts_compiler.cache_compiler_output(
B
Bartek Iwańczuk 已提交
41
    &module_specifier,
B
Bartek Iwańczuk 已提交
42 43
    &args.extension,
    &args.contents,
B
Bartek Iwańczuk 已提交
44 45
  )?;

B
Bartek Iwańczuk 已提交
46 47 48
  Ok(JsonOp::Sync(json!({})))
}

K
Kitson Kelly 已提交
49 50
#[derive(Deserialize, Debug)]
struct SpecifiersReferrerArgs {
51
  specifiers: Vec<String>,
52
  referrer: Option<String>,
B
Bartek Iwańczuk 已提交
53 54
}

K
Kitson Kelly 已提交
55
fn op_resolve_modules(
B
Bartek Iwańczuk 已提交
56
  state: &ThreadSafeState,
B
Bartek Iwańczuk 已提交
57
  args: Value,
R
Ryan Dahl 已提交
58
  _data: Option<ZeroCopyBuf>,
B
Bartek Iwańczuk 已提交
59
) -> Result<JsonOp, ErrBox> {
K
Kitson Kelly 已提交
60 61 62 63 64 65 66 67 68 69
  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 {
70
    let resolved_specifier = state.resolve(specifier, &referrer, is_main);
K
Kitson Kelly 已提交
71 72 73 74 75 76 77 78 79 80 81 82
    match resolved_specifier {
      Ok(ms) => specifiers.push(ms.as_str().to_owned()),
      Err(err) => return Err(err),
    }
  }

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

fn op_fetch_source_files(
  state: &ThreadSafeState,
  args: Value,
R
Ryan Dahl 已提交
83
  _data: Option<ZeroCopyBuf>,
K
Kitson Kelly 已提交
84 85 86 87
) -> Result<JsonOp, ErrBox> {
  let args: SpecifiersReferrerArgs = serde_json::from_value(args)?;

  let ref_specifier = if let Some(referrer) = args.referrer {
88 89
    let specifier = ModuleSpecifier::resolve_url(&referrer)
      .expect("Referrer is not a valid specifier");
K
Kitson Kelly 已提交
90
    Some(specifier)
91
  } else {
K
Kitson Kelly 已提交
92
    None
93 94
  };

95 96 97
  let mut futures = vec![];
  for specifier in &args.specifiers {
    let resolved_specifier =
K
Kitson Kelly 已提交
98
      ModuleSpecifier::resolve_url(&specifier).expect("Invalid specifier");
99
    let fut = state
100
      .global_state
101
      .file_fetcher
102
      .fetch_source_file_async(&resolved_specifier, ref_specifier.clone());
103 104
    futures.push(fut);
  }
B
Bartek Iwańczuk 已提交
105

106 107
  let global_state = state.global_state.clone();

108 109 110 111
  let future = Box::pin(async move {
    let files = try_join_all(futures).await?;

    // We want to get an array of futures that resolves to
112
    let v = files.into_iter().map(|f| {
113
      async {
114 115 116 117 118 119 120 121 122 123 124 125
        // 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
              .fetch_source_file_async(&types_specifier, ref_specifier.clone())
              .await?
          }
          _ => f,
        };
126 127 128 129 130 131 132 133 134 135
        // 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
              .compile_async(global_state.clone(), &file)
              .await?
              .code
136
          }
137 138 139 140 141 142 143 144 145
          _ => String::from_utf8(file.source_code).unwrap(),
        };
        Ok::<_, ErrBox>(json!({
          "url": file.url.to_string(),
          "filename": file.filename.to_str().unwrap(),
          "mediaType": file.media_type as i32,
          "sourceCode": source_code,
        }))
      }
K
Kitson Kelly 已提交
146
    });
147

148 149 150 151 152
    let v = try_join_all(v).await?;
    Ok(v.into())
  });

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