compiler.rs 3.9 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};
B
Bartek Iwańczuk 已提交
3 4 5
use crate::futures::future::try_join_all;
use crate::futures::future::FutureExt;
use crate::futures::future::TryFutureExt;
6
use crate::msg;
7
use crate::ops::json_op;
B
Bartek Iwańczuk 已提交
8
use crate::state::ThreadSafeState;
9
use deno::Loader;
B
Bartek Iwańczuk 已提交
10
use deno::*;
B
Bartek Iwańczuk 已提交
11

12 13 14 15 16 17 18 19 20 21 22 23
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 已提交
24 25 26 27 28 29 30
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CacheArgs {
  module_id: String,
  contents: String,
  extension: String,
}
B
Bartek Iwańczuk 已提交
31

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

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

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

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

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

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

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

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

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

B
Bartek Iwańczuk 已提交
81
  let future = try_join_all(futures)
K
Kitson Kelly 已提交
82 83
    .map_err(ErrBox::from)
    .and_then(move |files| {
84 85
      // We want to get an array of futures that resolves to
      let v: Vec<_> = files
K
Kitson Kelly 已提交
86 87
        .into_iter()
        .map(|file| {
88 89 90 91
          // 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 {
B
Bartek Iwańczuk 已提交
92
            return futures::future::Either::Left(
93 94 95
              global_state
                .wasm_compiler
                .compile_async(global_state.clone(), &file)
B
Bartek Iwańczuk 已提交
96 97 98
                .and_then(|compiled_mod| {
                  futures::future::ok((file, Some(compiled_mod.code)))
                }),
99 100
            );
          }
B
Bartek Iwańczuk 已提交
101
          futures::future::Either::Right(futures::future::ok((file, None)))
102 103
        })
        .collect();
B
Bartek Iwańczuk 已提交
104
      try_join_all(v)
105 106 107 108 109
    })
    .and_then(move |files_with_code| {
      let res = files_with_code
        .into_iter()
        .map(|(file, maybe_code)| {
K
Kitson Kelly 已提交
110 111 112 113
          json!({
            "url": file.url.to_string(),
            "filename": file.filename.to_str().unwrap(),
            "mediaType": file.media_type as i32,
114 115 116 117 118
            "sourceCode": if let Some(code) = maybe_code {
              code
            } else {
              String::from_utf8(file.source_code).unwrap()
            },
K
Kitson Kelly 已提交
119 120 121 122 123 124
          })
        })
        .collect();

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

B
Bartek Iwańczuk 已提交
126
  Ok(JsonOp::Async(future.boxed()))
B
Bartek Iwańczuk 已提交
127
}
128 129 130 131 132 133

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

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