compiler.rs 3.8 KB
Newer Older
B
Bartek Iwańczuk 已提交
1
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
B
Bartek Iwańczuk 已提交
2
use super::dispatch_json::{Deserialize, JsonOp, Value};
K
Kitson Kelly 已提交
3 4
use crate::futures::future::join_all;
use crate::futures::Future;
5
use crate::msg;
6
use crate::ops::json_op;
B
Bartek Iwańczuk 已提交
7
use crate::state::ThreadSafeState;
8
use deno::Loader;
B
Bartek Iwańczuk 已提交
9
use deno::*;
B
Bartek Iwańczuk 已提交
10

11 12 13 14 15 16 17 18 19 20 21 22
pub fn init(i: &mut Isolate, s: &ThreadSafeState) {
  i.register_op("cache", s.core_op(json_op(s.stateful_op(op_cache))));
  i.register_op(
    "fetch_source_files",
    s.core_op(json_op(s.stateful_op(op_fetch_source_files))),
  );
  i.register_op(
    "fetch_asset",
    s.core_op(json_op(s.stateful_op(op_fetch_asset))),
  );
}

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

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

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

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

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

#[derive(Deserialize)]
51 52
struct FetchSourceFilesArgs {
  specifiers: Vec<String>,
B
Bartek Iwańczuk 已提交
53
  referrer: String,
B
Bartek Iwańczuk 已提交
54 55
}

56
fn op_fetch_source_files(
B
Bartek Iwańczuk 已提交
57
  state: &ThreadSafeState,
B
Bartek Iwańczuk 已提交
58
  args: Value,
K
Kitson Kelly 已提交
59
  _data: Option<PinnedBuf>,
B
Bartek Iwańczuk 已提交
60
) -> Result<JsonOp, ErrBox> {
61
  let args: FetchSourceFilesArgs = serde_json::from_value(args)?;
B
Bartek Iwańczuk 已提交
62 63 64 65 66

  // 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;

67 68 69 70 71
  let mut futures = vec![];
  for specifier in &args.specifiers {
    let resolved_specifier =
      state.resolve(specifier, &args.referrer, false, is_dyn_import)?;
    let fut = state
72
      .global_state
73 74 75 76
      .file_fetcher
      .fetch_source_file_async(&resolved_specifier);
    futures.push(fut);
  }
B
Bartek Iwańczuk 已提交
77

78 79
  let global_state = state.global_state.clone();

K
Kitson Kelly 已提交
80 81 82
  let future = join_all(futures)
    .map_err(ErrBox::from)
    .and_then(move |files| {
83 84
      // We want to get an array of futures that resolves to
      let v: Vec<_> = files
K
Kitson Kelly 已提交
85 86
        .into_iter()
        .map(|file| {
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
          // Special handling of Wasm files:
          // compile them into JS first!
          // This allows TS to do correct export types.
          if file.media_type == msg::MediaType::Wasm {
            return futures::future::Either::A(
              global_state
                .wasm_compiler
                .compile_async(global_state.clone(), &file)
                .and_then(|compiled_mod| Ok((file, Some(compiled_mod.code)))),
            );
          }
          futures::future::Either::B(futures::future::ok((file, None)))
        })
        .collect();
      join_all(v)
    })
    .and_then(move |files_with_code| {
      let res = files_with_code
        .into_iter()
        .map(|(file, maybe_code)| {
K
Kitson Kelly 已提交
107 108 109 110
          json!({
            "url": file.url.to_string(),
            "filename": file.filename.to_str().unwrap(),
            "mediaType": file.media_type as i32,
111 112 113 114 115
            "sourceCode": if let Some(code) = maybe_code {
              code
            } else {
              String::from_utf8(file.source_code).unwrap()
            },
K
Kitson Kelly 已提交
116 117 118 119 120 121
          })
        })
        .collect();

      futures::future::ok(res)
    });
122

K
Kitson Kelly 已提交
123
  Ok(JsonOp::Async(Box::new(future)))
B
Bartek Iwańczuk 已提交
124
}
125 126 127 128 129 130

#[derive(Deserialize)]
struct FetchAssetArgs {
  name: String,
}

131
fn op_fetch_asset(
132 133 134 135 136
  _state: &ThreadSafeState,
  args: Value,
  _zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> {
  let args: FetchAssetArgs = serde_json::from_value(args)?;
137
  if let Some(source_code) = crate::js::get_asset(&args.name) {
138 139 140 141 142
    Ok(JsonOp::Sync(json!(source_code)))
  } else {
    panic!("op_fetch_asset bad asset {}", args.name)
  }
}