ops.rs 52.2 KB
Newer Older
R
Ryan Dahl 已提交
1
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
R
Ryan Dahl 已提交
2 3
use atty;
use crate::ansi;
A
Andy Hayden 已提交
4
use crate::errors;
5
use crate::errors::{DenoError, DenoResult, ErrorKind};
A
Andy Hayden 已提交
6 7
use crate::fs as deno_fs;
use crate::http_util;
8 9
use crate::js_errors::apply_source_map;
use crate::js_errors::JSErrorColor;
A
Andy Hayden 已提交
10 11 12 13 14 15 16
use crate::msg;
use crate::msg_util;
use crate::repl;
use crate::resolve_addr::resolve_addr;
use crate::resources;
use crate::resources::table_entries;
use crate::resources::Resource;
R
Ryan Dahl 已提交
17
use crate::startup_data;
18
use crate::state::ThreadSafeState;
A
Andy Hayden 已提交
19
use crate::tokio_util;
20
use crate::tokio_write;
A
Andy Hayden 已提交
21
use crate::version;
22
use crate::worker::root_specifier_to_url;
23
use crate::worker::Worker;
24
use deno::deno_buf;
25
use deno::js_check;
26 27 28
use deno::Buf;
use deno::JSError;
use deno::Op;
R
Ryan Dahl 已提交
29
use flatbuffers::FlatBufferBuilder;
30
use futures;
R
Ryan Dahl 已提交
31
use futures::Async;
R
Ryan Dahl 已提交
32
use futures::Poll;
R
Ryan Dahl 已提交
33 34
use futures::Sink;
use futures::Stream;
R
Ryan Dahl 已提交
35
use hyper;
36
use hyper::rt::Future;
37
use remove_dir_all::remove_dir_all;
38
use std;
F
F001 已提交
39
use std::convert::From;
40
use std::fs;
41
use std::net::Shutdown;
R
Ryan Dahl 已提交
42
use std::path::Path;
R
Ryan Dahl 已提交
43
use std::path::PathBuf;
44
use std::process::Command;
45
use std::time::{Duration, Instant, UNIX_EPOCH};
R
Ryan Dahl 已提交
46
use tokio;
47 48
use tokio::net::TcpListener;
use tokio::net::TcpStream;
49
use tokio_process::CommandExt;
R
Ryan Dahl 已提交
50
use tokio_threadpool;
51

R
Ryan Dahl 已提交
52 53 54 55 56
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt;

R
Ryan Dahl 已提交
57 58
type OpResult = DenoResult<Buf>;

59 60 61
pub type OpWithError = dyn Future<Item = Buf, Error = DenoError> + Send;

// TODO Ideally we wouldn't have to box the OpWithError being returned.
R
Ryan Dahl 已提交
62
// The box is just to make it easier to get a prototype refactor working.
R
Ryan Dahl 已提交
63
type OpCreator =
64
  fn(state: &ThreadSafeState, base: &msg::Base<'_>, data: deno_buf)
65 66
    -> Box<OpWithError>;

A
andy finch 已提交
67
pub type OpSelector = fn(inner_type: msg::Any) -> Option<OpCreator>;
R
Ryan Dahl 已提交
68

F
F001 已提交
69
#[inline]
R
Ryan Dahl 已提交
70 71 72 73
fn empty_buf() -> Buf {
  Box::new([])
}

R
Ryan Dahl 已提交
74
/// Processes raw messages from JavaScript.
75 76 77
/// This functions invoked every time Deno.core.dispatch() is called.
/// control corresponds to the first argument of Deno.core.dispatch().
/// data corresponds to the second argument of Deno.core.dispatch().
78
pub fn dispatch_all(
79
  state: &ThreadSafeState,
80 81
  control: &[u8],
  zero_copy: deno_buf,
82
  op_selector: OpSelector,
83
) -> (bool, Box<Op>) {
84 85
  let bytes_sent_control = control.len();
  let bytes_sent_zero_copy = zero_copy.len();
86
  let base = msg::get_root_as_base(&control);
R
Ryan Dahl 已提交
87
  let is_sync = base.sync();
88
  let inner_type = base.inner_type();
R
Ryan Dahl 已提交
89
  let cmd_id = base.cmd_id();
90

91 92 93
  let op_func: OpCreator = match op_selector(inner_type) {
    Some(v) => v,
    None => panic!("Unhandled message {}", msg::enum_name_any(inner_type)),
94 95
  };

96
  let op: Box<OpWithError> = op_func(state, &base, zero_copy);
97

98
  let state = state.clone();
99
  state.metrics_op_dispatched(bytes_sent_control, bytes_sent_zero_copy);
100

R
Format  
Ryan Dahl 已提交
101
  let boxed_op = Box::new(
102
    op.or_else(move |err: DenoError| -> Result<Buf, ()> {
R
Ryan Dahl 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115 116
      debug!("op err {}", err);
      // No matter whether we got an Err or Ok, we want a serialized message to
      // send back. So transform the DenoError into a deno_buf.
      let builder = &mut FlatBufferBuilder::new();
      let errmsg_offset = builder.create_string(&format!("{}", err));
      Ok(serialize_response(
        cmd_id,
        builder,
        msg::BaseArgs {
          error: Some(errmsg_offset),
          error_kind: err.kind(),
          ..Default::default()
        },
      ))
117
    }).and_then(move |buf: Buf| -> Result<Buf, ()> {
R
Ryan Dahl 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131
      // Handle empty responses. For sync responses we just want
      // to send null. For async we want to send a small message
      // with the cmd_id.
      let buf = if is_sync || buf.len() > 0 {
        buf
      } else {
        let builder = &mut FlatBufferBuilder::new();
        serialize_response(
          cmd_id,
          builder,
          msg::BaseArgs {
            ..Default::default()
          },
        )
R
Ryan Dahl 已提交
132
      };
133
      state.metrics_op_completed(buf.len());
R
Ryan Dahl 已提交
134
      Ok(buf)
135
    }).map_err(|err| panic!("unexpected error {:?}", err)),
R
Format  
Ryan Dahl 已提交
136
  );
137

R
Ryan Dahl 已提交
138 139
  debug!(
    "msg_from_js {} sync {}",
140
    msg::enum_name_any(inner_type),
R
Ryan Dahl 已提交
141 142
    base.sync()
  );
A
Andy Hayden 已提交
143
  (base.sync(), boxed_op)
144 145
}

A
andy finch 已提交
146 147 148 149 150 151 152 153 154 155 156
pub fn op_selector_compiler(inner_type: msg::Any) -> Option<OpCreator> {
  match inner_type {
    msg::Any::FetchModuleMetaData => Some(op_fetch_module_meta_data),
    msg::Any::WorkerGetMessage => Some(op_worker_get_message),
    msg::Any::WorkerPostMessage => Some(op_worker_post_message),
    msg::Any::Exit => Some(op_exit),
    msg::Any::Start => Some(op_start),
    _ => None,
  }
}

A
andy finch 已提交
157
/// Standard ops set for most isolates
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
pub fn op_selector_std(inner_type: msg::Any) -> Option<OpCreator> {
  match inner_type {
    msg::Any::Accept => Some(op_accept),
    msg::Any::Chdir => Some(op_chdir),
    msg::Any::Chmod => Some(op_chmod),
    msg::Any::Close => Some(op_close),
    msg::Any::CopyFile => Some(op_copy_file),
    msg::Any::Cwd => Some(op_cwd),
    msg::Any::Dial => Some(op_dial),
    msg::Any::Environ => Some(op_env),
    msg::Any::Exit => Some(op_exit),
    msg::Any::Fetch => Some(op_fetch),
    msg::Any::FormatError => Some(op_format_error),
    msg::Any::GlobalTimer => Some(op_global_timer),
    msg::Any::GlobalTimerStop => Some(op_global_timer_stop),
    msg::Any::IsTTY => Some(op_is_tty),
174
    msg::Any::Link => Some(op_link),
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    msg::Any::Listen => Some(op_listen),
    msg::Any::MakeTempDir => Some(op_make_temp_dir),
    msg::Any::Metrics => Some(op_metrics),
    msg::Any::Mkdir => Some(op_mkdir),
    msg::Any::Now => Some(op_now),
    msg::Any::Open => Some(op_open),
    msg::Any::PermissionRevoke => Some(op_revoke_permission),
    msg::Any::Permissions => Some(op_permissions),
    msg::Any::Read => Some(op_read),
    msg::Any::ReadDir => Some(op_read_dir),
    msg::Any::Readlink => Some(op_read_link),
    msg::Any::Remove => Some(op_remove),
    msg::Any::Rename => Some(op_rename),
    msg::Any::ReplReadline => Some(op_repl_readline),
    msg::Any::ReplStart => Some(op_repl_start),
    msg::Any::Resources => Some(op_resources),
    msg::Any::Run => Some(op_run),
    msg::Any::RunStatus => Some(op_run_status),
    msg::Any::Seek => Some(op_seek),
    msg::Any::SetEnv => Some(op_set_env),
    msg::Any::Shutdown => Some(op_shutdown),
    msg::Any::Start => Some(op_start),
    msg::Any::Stat => Some(op_stat),
    msg::Any::Symlink => Some(op_symlink),
    msg::Any::Truncate => Some(op_truncate),
A
andy finch 已提交
200 201 202 203
    msg::Any::CreateWorker => Some(op_create_worker),
    msg::Any::HostGetWorkerClosed => Some(op_host_get_worker_closed),
    msg::Any::HostGetMessage => Some(op_host_get_message),
    msg::Any::HostPostMessage => Some(op_host_post_message),
204
    msg::Any::Write => Some(op_write),
205 206

    // TODO(ry) split these out so that only the appropriate Workers can access
A
andy finch 已提交
207
    // them.
208 209 210
    msg::Any::WorkerGetMessage => Some(op_worker_get_message),
    msg::Any::WorkerPostMessage => Some(op_worker_post_message),

211 212
    _ => None,
  }
213 214
}

215 216 217 218
// Returns a milliseconds and nanoseconds subsec
// since the start time of the deno runtime.
// If the High precision flag is not set, the
// nanoseconds are rounded on 2ms.
D
Dmitry Sharshakov 已提交
219
fn op_now(
220
  state: &ThreadSafeState,
D
Dmitry Sharshakov 已提交
221
  base: &msg::Base<'_>,
222 223
  data: deno_buf,
) -> Box<OpWithError> {
D
Dmitry Sharshakov 已提交
224
  assert_eq!(data.len(), 0);
225 226
  let seconds = state.start_time.elapsed().as_secs();
  let mut subsec_nanos = state.start_time.elapsed().subsec_nanos();
227
  let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
228 229 230 231

  // If the permission is not enabled
  // Round the nano result on 2 milliseconds
  // see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision
232
  if !state.permissions.allows_high_precision() {
233 234
    subsec_nanos -= subsec_nanos % reduced_time_precision
  }
D
Dmitry Sharshakov 已提交
235 236

  let builder = &mut FlatBufferBuilder::new();
237 238 239 240 241 242 243
  let inner = msg::NowRes::create(
    builder,
    &msg::NowResArgs {
      seconds,
      subsec_nanos,
    },
  );
D
Dmitry Sharshakov 已提交
244 245 246 247 248 249 250 251 252 253 254
  ok_future(serialize_response(
    base.cmd_id(),
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::NowRes,
      ..Default::default()
    },
  ))
}

D
Dmitry Sharshakov 已提交
255
fn op_is_tty(
256
  _state: &ThreadSafeState,
D
Dmitry Sharshakov 已提交
257
  base: &msg::Base<'_>,
258 259
  _data: deno_buf,
) -> Box<OpWithError> {
D
Dmitry Sharshakov 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
  let builder = &mut FlatBufferBuilder::new();
  let inner = msg::IsTTYRes::create(
    builder,
    &msg::IsTTYResArgs {
      stdin: atty::is(atty::Stream::Stdin),
      stdout: atty::is(atty::Stream::Stdout),
      stderr: atty::is(atty::Stream::Stderr),
    },
  );
  ok_future(serialize_response(
    base.cmd_id(),
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::IsTTYRes,
      ..Default::default()
    },
  ))
}

R
Ryan Dahl 已提交
280
fn op_exit(
281
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
282
  base: &msg::Base<'_>,
283 284
  _data: deno_buf,
) -> Box<OpWithError> {
285 286
  let inner = base.inner_as_exit().unwrap();
  std::process::exit(inner.code())
R
Ryan Dahl 已提交
287 288
}

R
Ryan Dahl 已提交
289
fn op_start(
290
  state: &ThreadSafeState,
A
Andy Hayden 已提交
291
  base: &msg::Base<'_>,
292 293
  data: deno_buf,
) -> Box<OpWithError> {
294
  assert_eq!(data.len(), 0);
R
Ryan Dahl 已提交
295
  let mut builder = FlatBufferBuilder::new();
296

297
  let state = state;
B
Bert Belder 已提交
298
  let argv = state.argv.iter().map(String::as_str).collect::<Vec<_>>();
299 300 301
  let argv_off = builder.create_vector_of_strings(argv.as_slice());

  let cwd_path = std::env::current_dir().unwrap();
R
Ryan Dahl 已提交
302
  let cwd_off =
303
    builder.create_string(deno_fs::normalize_path(cwd_path.as_ref()).as_ref());
304

305 306 307
  let exec_path =
    builder.create_string(std::env::current_exe().unwrap().to_str().unwrap());

308
  let v8_version = version::v8();
309 310
  let v8_version_off = builder.create_string(v8_version);

311
  let deno_version = version::DENO;
312 313
  let deno_version_off = builder.create_string(deno_version);

314
  let main_module = state.main_module().map(|m| builder.create_string(&m));
R
Ryan Dahl 已提交
315

316
  let inner = msg::StartRes::create(
R
Ryan Dahl 已提交
317
    &mut builder,
318 319
    &msg::StartResArgs {
      cwd: Some(cwd_off),
R
Ryan Dahl 已提交
320
      pid: std::process::id(),
321
      argv: Some(argv_off),
R
Ryan Dahl 已提交
322
      main_module,
323 324 325
      debug_flag: state.flags.log_debug,
      types_flag: state.flags.types,
      version_flag: state.flags.version,
326 327
      v8_version: Some(v8_version_off),
      deno_version: Some(deno_version_off),
R
Ryan Dahl 已提交
328
      no_color: !ansi::use_color(),
329
      exec_path: Some(exec_path),
330 331 332 333
      ..Default::default()
    },
  );

R
Ryan Dahl 已提交
334
  ok_future(serialize_response(
R
Ryan Dahl 已提交
335 336 337
    base.cmd_id(),
    &mut builder,
    msg::BaseArgs {
338 339
      inner_type: msg::Any::StartRes,
      inner: Some(inner.as_union_value()),
340 341
      ..Default::default()
    },
342
  ))
R
Ryan Dahl 已提交
343 344
}

345
fn op_format_error(
346
  state: &ThreadSafeState,
347
  base: &msg::Base<'_>,
348 349
  data: deno_buf,
) -> Box<OpWithError> {
350 351 352 353 354
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_format_error().unwrap();
  let orig_error = String::from(inner.error().unwrap());

  let js_error = JSError::from_v8_exception(&orig_error).unwrap();
355
  let js_error_mapped = apply_source_map(&js_error, &state.dir);
356
  let js_error_string = JSErrorColor(&js_error_mapped).to_string();
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378

  let mut builder = FlatBufferBuilder::new();
  let new_error = builder.create_string(&js_error_string);

  let inner = msg::FormatErrorRes::create(
    &mut builder,
    &msg::FormatErrorResArgs {
      error: Some(new_error),
    },
  );

  ok_future(serialize_response(
    base.cmd_id(),
    &mut builder,
    msg::BaseArgs {
      inner_type: msg::Any::FormatErrorRes,
      inner: Some(inner.as_union_value()),
      ..Default::default()
    },
  ))
}

R
Ryan Dahl 已提交
379
fn serialize_response(
R
Ryan Dahl 已提交
380
  cmd_id: u32,
A
Andy Hayden 已提交
381 382
  builder: &mut FlatBufferBuilder<'_>,
  mut args: msg::BaseArgs<'_>,
R
Ryan Dahl 已提交
383 384
) -> Buf {
  args.cmd_id = cmd_id;
R
Ryan Dahl 已提交
385 386
  let base = msg::Base::create(builder, &args);
  msg::finish_base_buffer(builder, base);
R
Ryan Dahl 已提交
387
  let data = builder.finished_data();
R
Ryan Dahl 已提交
388
  // println!("serialize_response {:x?}", data);
F
F001 已提交
389
  data.into()
390 391
}

392
#[inline]
393
pub fn ok_future(buf: Buf) -> Box<OpWithError> {
R
Ryan Dahl 已提交
394 395 396 397
  Box::new(futures::future::ok(buf))
}

// Shout out to Earl Sweatshirt.
398
#[inline]
399
pub fn odd_future(err: DenoError) -> Box<OpWithError> {
R
Ryan Dahl 已提交
400
  Box::new(futures::future::err(err))
401 402
}

Y
Yoshiya Hinosawa 已提交
403
// https://github.com/denoland/deno/blob/golang/os.go#L100-L154
K
Kitson Kelly 已提交
404
fn op_fetch_module_meta_data(
405
  state: &ThreadSafeState,
A
Andy Hayden 已提交
406
  base: &msg::Base<'_>,
407 408
  data: deno_buf,
) -> Box<OpWithError> {
409
  assert_eq!(data.len(), 0);
K
Kitson Kelly 已提交
410
  let inner = base.inner_as_fetch_module_meta_data().unwrap();
R
Ryan Dahl 已提交
411
  let cmd_id = base.cmd_id();
R
Ryan Dahl 已提交
412 413
  let specifier = inner.specifier().unwrap();
  let referrer = inner.referrer().unwrap();
R
Ryan Dahl 已提交
414

415
  assert_eq!(state.dir.root.join("gen"), state.dir.gen, "Sanity check");
R
Ryan Dahl 已提交
416

417
  let use_cache = !state.flags.reload;
418

R
Ryan Dahl 已提交
419 420
  Box::new(futures::future::result(|| -> OpResult {
    let builder = &mut FlatBufferBuilder::new();
421
    // TODO(ry) Use fetch_module_meta_data_async.
422
    let out = state
423 424
      .dir
      .fetch_module_meta_data(specifier, referrer, use_cache)?;
K
Kitson Kelly 已提交
425 426
    let data_off = builder.create_vector(out.source_code.as_slice());
    let msg_args = msg::FetchModuleMetaDataResArgs {
R
Ryan Dahl 已提交
427 428
      module_name: Some(builder.create_string(&out.module_name)),
      filename: Some(builder.create_string(&out.filename)),
K
Kitson Kelly 已提交
429
      media_type: out.media_type,
K
Kitson Kelly 已提交
430
      data: Some(data_off),
R
Ryan Dahl 已提交
431
    };
K
Kitson Kelly 已提交
432
    let inner = msg::FetchModuleMetaDataRes::create(builder, &msg_args);
R
Ryan Dahl 已提交
433
    Ok(serialize_response(
R
Ryan Dahl 已提交
434 435 436
      cmd_id,
      builder,
      msg::BaseArgs {
437
        inner: Some(inner.as_union_value()),
K
Kitson Kelly 已提交
438
        inner_type: msg::Any::FetchModuleMetaDataRes,
R
Ryan Dahl 已提交
439 440 441 442
        ..Default::default()
      },
    ))
  }()))
443 444
}

S
Shiva Prasanth 已提交
445
fn op_chdir(
446
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
447
  base: &msg::Base<'_>,
448 449
  data: deno_buf,
) -> Box<OpWithError> {
S
Shiva Prasanth 已提交
450 451 452 453
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_chdir().unwrap();
  let directory = inner.directory().unwrap();
  Box::new(futures::future::result(|| -> OpResult {
A
Andy Hayden 已提交
454
    std::env::set_current_dir(&directory)?;
S
Shiva Prasanth 已提交
455 456 457 458
    Ok(empty_buf())
  }()))
}

R
Ryan Dahl 已提交
459
fn op_global_timer_stop(
460
  state: &ThreadSafeState,
A
Andy Hayden 已提交
461
  base: &msg::Base<'_>,
462 463
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
464
  assert!(base.sync());
465
  assert_eq!(data.len(), 0);
466
  let state = state;
467
  let mut t = state.global_timer.lock().unwrap();
R
Ryan Dahl 已提交
468
  t.cancel();
R
Ryan Dahl 已提交
469 470 471
  ok_future(empty_buf())
}

R
Ryan Dahl 已提交
472
fn op_global_timer(
473
  state: &ThreadSafeState,
R
Ryan Dahl 已提交
474
  base: &msg::Base<'_>,
475 476
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
477 478 479 480 481 482 483
  assert!(!base.sync());
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_global_timer().unwrap();
  let val = inner.timeout();
  assert!(val >= 0);

484
  let state = state;
485
  let mut t = state.global_timer.lock().unwrap();
R
Ryan Dahl 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
  let deadline = Instant::now() + Duration::from_millis(val as u64);
  let f = t.new_timeout(deadline);

  Box::new(f.then(move |_| {
    let builder = &mut FlatBufferBuilder::new();
    let inner =
      msg::GlobalTimerRes::create(builder, &msg::GlobalTimerResArgs {});
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::GlobalTimerRes,
        ..Default::default()
      },
    ))
  }))
}

R
Ryan Dahl 已提交
505
fn op_set_env(
506
  state: &ThreadSafeState,
A
Andy Hayden 已提交
507
  base: &msg::Base<'_>,
508 509
  data: deno_buf,
) -> Box<OpWithError> {
510
  assert_eq!(data.len(), 0);
511 512 513
  let inner = base.inner_as_set_env().unwrap();
  let key = inner.key().unwrap();
  let value = inner.value().unwrap();
514
  if let Err(e) = state.check_env() {
515
    return odd_future(e);
516 517
  }
  std::env::set_var(key, value);
R
Ryan Dahl 已提交
518
  ok_future(empty_buf())
519 520
}

521
fn op_env(
522
  state: &ThreadSafeState,
523 524 525
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
526
  assert_eq!(data.len(), 0);
R
Ryan Dahl 已提交
527
  let cmd_id = base.cmd_id();
R
Ryan Dahl 已提交
528

529
  if let Err(e) = state.check_env() {
530
    return odd_future(e);
531 532
  }

R
Ryan Dahl 已提交
533
  let builder = &mut FlatBufferBuilder::new();
R
Format.  
Ryan Dahl 已提交
534
  let vars: Vec<_> = std::env::vars()
R
Ryan Dahl 已提交
535 536
    .map(|(key, value)| msg_util::serialize_key_value(builder, &key, &value))
    .collect();
R
Ryan Dahl 已提交
537
  let tables = builder.create_vector(&vars);
538
  let inner = msg::EnvironRes::create(
539
    builder,
A
Andy Hayden 已提交
540
    &msg::EnvironResArgs { map: Some(tables) },
541
  );
R
Ryan Dahl 已提交
542
  ok_future(serialize_response(
R
Ryan Dahl 已提交
543
    cmd_id,
544
    builder,
R
Ryan Dahl 已提交
545
    msg::BaseArgs {
546 547
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::EnvironRes,
548 549 550 551 552
      ..Default::default()
    },
  ))
}

553
fn op_permissions(
554
  state: &ThreadSafeState,
555
  base: &msg::Base<'_>,
556 557
  data: deno_buf,
) -> Box<OpWithError> {
558 559 560 561 562 563
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let builder = &mut FlatBufferBuilder::new();
  let inner = msg::PermissionsRes::create(
    builder,
    &msg::PermissionsResArgs {
564 565 566 567 568 569
      run: state.permissions.allows_run(),
      read: state.permissions.allows_read(),
      write: state.permissions.allows_write(),
      net: state.permissions.allows_net(),
      env: state.permissions.allows_env(),
      high_precision: state.permissions.allows_high_precision(),
570 571 572 573 574 575 576 577 578 579 580 581 582 583
    },
  );
  ok_future(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::PermissionsRes,
      ..Default::default()
    },
  ))
}

fn op_revoke_permission(
584
  state: &ThreadSafeState,
585
  base: &msg::Base<'_>,
586 587
  data: deno_buf,
) -> Box<OpWithError> {
588 589 590 591
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_permission_revoke().unwrap();
  let permission = inner.permission().unwrap();
  let result = match permission {
592 593 594 595 596 597
    "run" => state.permissions.revoke_run(),
    "read" => state.permissions.revoke_read(),
    "write" => state.permissions.revoke_write(),
    "net" => state.permissions.revoke_net(),
    "env" => state.permissions.revoke_env(),
    "highPrecision" => state.permissions.revoke_high_precision(),
598 599 600 601 602 603 604 605
    _ => Ok(()),
  };
  if let Err(e) = result {
    return odd_future(e);
  }
  ok_future(empty_buf())
}

R
Ryan Dahl 已提交
606
fn op_fetch(
607
  state: &ThreadSafeState,
A
Andy Hayden 已提交
608
  base: &msg::Base<'_>,
609 610
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
611
  let inner = base.inner_as_fetch().unwrap();
R
Ryan Dahl 已提交
612
  let cmd_id = base.cmd_id();
613 614 615 616 617

  let header = inner.header().unwrap();
  assert!(header.is_request());
  let url = header.url().unwrap();

A
Andy Hayden 已提交
618
  let body = if data.is_empty() {
R
Ryan Dahl 已提交
619 620
    hyper::Body::empty()
  } else {
621
    hyper::Body::from(Vec::from(&*data))
R
Ryan Dahl 已提交
622 623
  };

624 625 626 627 628
  let maybe_req = msg_util::deserialize_request(header, body);
  if let Err(e) = maybe_req {
    return odd_future(e);
  }
  let req = maybe_req.unwrap();
R
Ryan Dahl 已提交
629

630
  if let Err(e) = state.check_net(url) {
631
    return odd_future(e);
R
Ryan Dahl 已提交
632 633
  }

R
Ryan Dahl 已提交
634
  let client = http_util::get_client();
R
Ryan Dahl 已提交
635

R
Ryan Dahl 已提交
636
  debug!("Before fetch {}", url);
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
  let future =
    client
      .request(req)
      .map_err(DenoError::from)
      .and_then(move |res| {
        let builder = &mut FlatBufferBuilder::new();
        let header_off = msg_util::serialize_http_response(builder, &res);
        let body = res.into_body();
        let body_resource = resources::add_hyper_body(body);
        let inner = msg::FetchRes::create(
          builder,
          &msg::FetchResArgs {
            header: Some(header_off),
            body_rid: body_resource.rid,
          },
        );
Q
qti3e 已提交
653

654 655 656 657 658 659 660 661 662 663
        Ok(serialize_response(
          cmd_id,
          builder,
          msg::BaseArgs {
            inner: Some(inner.as_union_value()),
            inner_type: msg::Any::FetchRes,
            ..Default::default()
          },
        ))
      });
R
Ryan Dahl 已提交
664
  Box::new(future)
R
Ryan Dahl 已提交
665 666
}

R
Ryan Dahl 已提交
667 668 669 670 671 672 673 674 675 676 677
// This is just type conversion. Implement From trait?
// See https://github.com/tokio-rs/tokio/blob/ffd73a64e7ec497622b7f939e38017afe7124dc4/tokio-fs/src/lib.rs#L76-L85
fn convert_blocking<F>(f: F) -> Poll<Buf, DenoError>
where
  F: FnOnce() -> DenoResult<Buf>,
{
  use futures::Async::*;
  match tokio_threadpool::blocking(f) {
    Ok(Ready(Ok(v))) => Ok(v.into()),
    Ok(Ready(Err(err))) => Err(err),
    Ok(NotReady) => Ok(NotReady),
678
    Err(err) => panic!("blocking error {}", err),
R
Ryan Dahl 已提交
679 680 681
  }
}

682
fn blocking<F>(is_sync: bool, f: F) -> Box<OpWithError>
683 684 685 686 687 688 689 690
where
  F: 'static + Send + FnOnce() -> DenoResult<Buf>,
{
  if is_sync {
    Box::new(futures::future::result(f()))
  } else {
    Box::new(tokio_util::poll_fn(move || convert_blocking(f)))
  }
R
Ryan Dahl 已提交
691 692
}

R
Ryan Dahl 已提交
693
fn op_make_temp_dir(
694
  state: &ThreadSafeState,
A
Andy Hayden 已提交
695
  base: &msg::Base<'_>,
696 697
  data: deno_buf,
) -> Box<OpWithError> {
698
  assert_eq!(data.len(), 0);
R
Ryan Dahl 已提交
699
  let base = Box::new(*base);
700
  let inner = base.inner_as_make_temp_dir().unwrap();
R
Ryan Dahl 已提交
701 702
  let cmd_id = base.cmd_id();

703
  // FIXME
704
  if let Err(e) = state.check_write("make_temp") {
705
    return odd_future(e);
B
Bert Belder 已提交
706
  }
R
Ryan Dahl 已提交
707

708 709 710
  let dir = inner.dir().map(PathBuf::from);
  let prefix = inner.prefix().map(String::from);
  let suffix = inner.suffix().map(String::from);
R
Ryan Dahl 已提交
711

712
  blocking(base.sync(), move || -> OpResult {
R
Ryan Dahl 已提交
713
    // TODO(piscisaureus): use byte vector for paths, not a string.
Y
Yoshiya Hinosawa 已提交
714
    // See https://github.com/denoland/deno/issues/627.
R
Ryan Dahl 已提交
715
    // We can't assume that paths are always valid utf8 strings.
R
Ryan Dahl 已提交
716 717 718 719 720 721
    let path = deno_fs::make_temp_dir(
      // Converting Option<String> to Option<&str>
      dir.as_ref().map(|x| &**x),
      prefix.as_ref().map(|x| &**x),
      suffix.as_ref().map(|x| &**x),
    )?;
R
Ryan Dahl 已提交
722 723
    let builder = &mut FlatBufferBuilder::new();
    let path_off = builder.create_string(path.to_str().unwrap());
724
    let inner = msg::MakeTempDirRes::create(
R
Ryan Dahl 已提交
725 726 727 728 729
      builder,
      &msg::MakeTempDirResArgs {
        path: Some(path_off),
      },
    );
R
Ryan Dahl 已提交
730
    Ok(serialize_response(
R
Ryan Dahl 已提交
731 732 733
      cmd_id,
      builder,
      msg::BaseArgs {
734 735
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::MakeTempDirRes,
R
Ryan Dahl 已提交
736 737 738
        ..Default::default()
      },
    ))
R
Ryan Dahl 已提交
739
  })
B
Bert Belder 已提交
740 741
}

R
Ryan Dahl 已提交
742
fn op_mkdir(
743
  state: &ThreadSafeState,
A
Andy Hayden 已提交
744
  base: &msg::Base<'_>,
745 746
  data: deno_buf,
) -> Box<OpWithError> {
747
  assert_eq!(data.len(), 0);
748 749
  let inner = base.inner_as_mkdir().unwrap();
  let path = String::from(inner.path().unwrap());
750 751
  let recursive = inner.recursive();
  let mode = inner.mode();
R
Ryan Dahl 已提交
752

753
  if let Err(e) = state.check_write(&path) {
754
    return odd_future(e);
R
Ryan Dahl 已提交
755
  }
756

757
  blocking(base.sync(), move || {
R
Ryan Dahl 已提交
758
    debug!("op_mkdir {}", path);
759
    deno_fs::mkdir(Path::new(&path), mode, recursive)?;
R
Ryan Dahl 已提交
760
    Ok(empty_buf())
R
Ryan Dahl 已提交
761
  })
S
Sajjad Hashemian 已提交
762 763
}

764
fn op_chmod(
765
  state: &ThreadSafeState,
A
Andy Hayden 已提交
766
  base: &msg::Base<'_>,
767 768
  data: deno_buf,
) -> Box<OpWithError> {
769 770 771 772 773
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_chmod().unwrap();
  let _mode = inner.mode();
  let path = String::from(inner.path().unwrap());

774
  if let Err(e) = state.check_write(&path) {
775
    return odd_future(e);
776 777
  }

778
  blocking(base.sync(), move || {
779 780 781 782 783 784 785
    debug!("op_chmod {}", &path);
    let path = PathBuf::from(&path);
    // Still check file/dir exists on windows
    let _metadata = fs::metadata(&path)?;
    // Only work in unix
    #[cfg(any(unix))]
    {
786
      // We need to use underscore to compile in Windows.
B
bokuweb 已提交
787 788 789 790
      #[cfg_attr(
        feature = "cargo-clippy",
        allow(clippy::used_underscore_binding)
      )]
791
      let mut permissions = _metadata.permissions();
B
bokuweb 已提交
792 793 794 795
      #[cfg_attr(
        feature = "cargo-clippy",
        allow(clippy::used_underscore_binding)
      )]
796 797 798 799 800 801 802
      permissions.set_mode(_mode);
      fs::set_permissions(&path, permissions)?;
    }
    Ok(empty_buf())
  })
}

R
Ryan Dahl 已提交
803
fn op_open(
804
  state: &ThreadSafeState,
A
Andy Hayden 已提交
805
  base: &msg::Base<'_>,
806 807
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
808 809
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
810
  let inner = base.inner_as_open().unwrap();
811 812
  let filename_str = inner.filename().unwrap();
  let filename = PathBuf::from(&filename_str);
B
Bartek Iwańczuk 已提交
813
  let mode = inner.mode().unwrap();
R
Ryan Dahl 已提交
814

B
Bartek Iwańczuk 已提交
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
  let mut open_options = tokio::fs::OpenOptions::new();

  match mode {
    "r" => {
      open_options.read(true);
    }
    "r+" => {
      open_options.read(true).write(true);
    }
    "w" => {
      open_options.create(true).write(true).truncate(true);
    }
    "w+" => {
      open_options
        .read(true)
        .create(true)
        .write(true)
        .truncate(true);
    }
    "a" => {
      open_options.create(true).append(true);
    }
    "a+" => {
      open_options.read(true).create(true).append(true);
    }
    "x" => {
      open_options.create_new(true).write(true);
    }
    "x+" => {
      open_options.create_new(true).read(true).write(true);
    }
    &_ => {
      panic!("Unknown file open mode.");
    }
  }

D
Dmitry Sharshakov 已提交
851 852
  match mode {
    "r" => {
853
      if let Err(e) = state.check_read(&filename_str) {
D
Dmitry Sharshakov 已提交
854 855 856 857
        return odd_future(e);
      }
    }
    "w" | "a" | "x" => {
858
      if let Err(e) = state.check_write(&filename_str) {
D
Dmitry Sharshakov 已提交
859 860 861 862
        return odd_future(e);
      }
    }
    &_ => {
863
      if let Err(e) = state.check_read(&filename_str) {
D
Dmitry Sharshakov 已提交
864 865
        return odd_future(e);
      }
866
      if let Err(e) = state.check_write(&filename_str) {
D
Dmitry Sharshakov 已提交
867 868
        return odd_future(e);
      }
F
F001 已提交
869 870 871
    }
  }

B
Bartek Iwańczuk 已提交
872 873
  let op = open_options
    .open(filename)
A
Andy Hayden 已提交
874
    .map_err(DenoError::from)
R
Ryan Dahl 已提交
875
    .and_then(move |fs_file| -> OpResult {
R
Ryan Dahl 已提交
876
      let resource = resources::add_fs_file(fs_file);
R
Ryan Dahl 已提交
877
      let builder = &mut FlatBufferBuilder::new();
A
Andy Hayden 已提交
878 879
      let inner =
        msg::OpenRes::create(builder, &msg::OpenResArgs { rid: resource.rid });
R
Ryan Dahl 已提交
880 881 882 883
      Ok(serialize_response(
        cmd_id,
        builder,
        msg::BaseArgs {
884 885
          inner: Some(inner.as_union_value()),
          inner_type: msg::Any::OpenRes,
R
Ryan Dahl 已提交
886 887 888 889 890 891 892
          ..Default::default()
        },
      ))
    });
  Box::new(op)
}

R
Ryan Dahl 已提交
893
fn op_close(
894
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
895
  base: &msg::Base<'_>,
896 897
  data: deno_buf,
) -> Box<OpWithError> {
898
  assert_eq!(data.len(), 0);
R
Ryan Dahl 已提交
899 900
  let inner = base.inner_as_close().unwrap();
  let rid = inner.rid();
901
  match resources::lookup(rid) {
R
Ryan Dahl 已提交
902
    None => odd_future(errors::bad_resource()),
R
Ryan Dahl 已提交
903
    Some(resource) => {
904 905 906 907 908 909
      resource.close();
      ok_future(empty_buf())
    }
  }
}

910
fn op_shutdown(
911
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
912
  base: &msg::Base<'_>,
913 914
  data: deno_buf,
) -> Box<OpWithError> {
915 916 917 918 919
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_shutdown().unwrap();
  let rid = inner.rid();
  let how = inner.how();
  match resources::lookup(rid) {
J
J2P 已提交
920
    None => odd_future(errors::bad_resource()),
921 922 923 924 925 926
    Some(mut resource) => {
      let shutdown_mode = match how {
        0 => Shutdown::Read,
        1 => Shutdown::Write,
        _ => unimplemented!(),
      };
927
      blocking(base.sync(), move || {
928 929 930 931 932 933 934 935
        // Use UFCS for disambiguation
        Resource::shutdown(&mut resource, shutdown_mode)?;
        Ok(empty_buf())
      })
    }
  }
}

R
Ryan Dahl 已提交
936
fn op_read(
937
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
938
  base: &msg::Base<'_>,
939 940
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
941
  let cmd_id = base.cmd_id();
942 943
  let inner = base.inner_as_read().unwrap();
  let rid = inner.rid();
R
Ryan Dahl 已提交
944

R
Ryan Dahl 已提交
945
  match resources::lookup(rid) {
R
Ryan Dahl 已提交
946
    None => odd_future(errors::bad_resource()),
947
    Some(resource) => {
948
      let op = tokio::io::read(resource, data)
A
Andy Hayden 已提交
949
        .map_err(DenoError::from)
950 951
        .and_then(move |(_resource, _buf, nread)| {
          let builder = &mut FlatBufferBuilder::new();
952
          let inner = msg::ReadRes::create(
953 954 955 956 957 958 959 960 961 962
            builder,
            &msg::ReadResArgs {
              nread: nread as u32,
              eof: nread == 0,
            },
          );
          Ok(serialize_response(
            cmd_id,
            builder,
            msg::BaseArgs {
963 964
              inner: Some(inner.as_union_value()),
              inner_type: msg::Any::ReadRes,
965 966 967 968
              ..Default::default()
            },
          ))
        });
R
Ryan Dahl 已提交
969 970 971 972 973
      Box::new(op)
    }
  }
}

R
Ryan Dahl 已提交
974
fn op_write(
975
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
976
  base: &msg::Base<'_>,
977 978
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
979
  let cmd_id = base.cmd_id();
980 981
  let inner = base.inner_as_write().unwrap();
  let rid = inner.rid();
R
Ryan Dahl 已提交
982

R
Ryan Dahl 已提交
983
  match resources::lookup(rid) {
R
Ryan Dahl 已提交
984
    None => odd_future(errors::bad_resource()),
985
    Some(resource) => {
986
      let op = tokio_write::write(resource, data)
A
Andy Hayden 已提交
987
        .map_err(DenoError::from)
R
Ryan Dahl 已提交
988
        .and_then(move |(_resource, _buf, nwritten)| {
989
          let builder = &mut FlatBufferBuilder::new();
990
          let inner = msg::WriteRes::create(
991 992
            builder,
            &msg::WriteResArgs {
R
Ryan Dahl 已提交
993
              nbyte: nwritten as u32,
994 995 996 997 998 999
            },
          );
          Ok(serialize_response(
            cmd_id,
            builder,
            msg::BaseArgs {
1000 1001
              inner: Some(inner.as_union_value()),
              inner_type: msg::Any::WriteRes,
1002 1003 1004 1005
              ..Default::default()
            },
          ))
        });
R
Ryan Dahl 已提交
1006 1007 1008 1009 1010
      Box::new(op)
    }
  }
}

1011
fn op_seek(
1012
  _state: &ThreadSafeState,
1013
  base: &msg::Base<'_>,
1014 1015
  data: deno_buf,
) -> Box<OpWithError> {
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
  assert_eq!(data.len(), 0);
  let _cmd_id = base.cmd_id();
  let inner = base.inner_as_seek().unwrap();
  let rid = inner.rid();
  let offset = inner.offset();
  let whence = inner.whence();

  match resources::lookup(rid) {
    None => odd_future(errors::bad_resource()),
    Some(resource) => {
      let op = resources::seek(resource, offset, whence)
        .and_then(move |_| Ok(empty_buf()));
      Box::new(op)
    }
  }
}

R
Ryan Dahl 已提交
1033
fn op_remove(
1034
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1035
  base: &msg::Base<'_>,
1036 1037
  data: deno_buf,
) -> Box<OpWithError> {
1038
  assert_eq!(data.len(), 0);
1039
  let inner = base.inner_as_remove().unwrap();
1040 1041
  let path_ = inner.path().unwrap();
  let path = PathBuf::from(path_);
1042
  let recursive = inner.recursive();
1043

1044
  if let Err(e) = state.check_write(path.to_str().unwrap()) {
1045
    return odd_future(e);
1046
  }
1047

1048
  blocking(base.sync(), move || {
R
Ryan Dahl 已提交
1049
    debug!("op_remove {}", path.display());
R
Ryan Dahl 已提交
1050
    let metadata = fs::metadata(&path)?;
1051
    if metadata.is_file() {
R
Ryan Dahl 已提交
1052
      fs::remove_file(&path)?;
A
Andy Hayden 已提交
1053 1054
    } else if recursive {
      remove_dir_all(&path)?;
1055
    } else {
A
Andy Hayden 已提交
1056
      fs::remove_dir(&path)?;
1057
    }
R
Ryan Dahl 已提交
1058
    Ok(empty_buf())
R
Ryan Dahl 已提交
1059
  })
1060 1061
}

R
Ryan Dahl 已提交
1062
fn op_copy_file(
1063
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1064
  base: &msg::Base<'_>,
1065 1066
  data: deno_buf,
) -> Box<OpWithError> {
1067
  assert_eq!(data.len(), 0);
1068
  let inner = base.inner_as_copy_file().unwrap();
D
Dmitry Sharshakov 已提交
1069 1070
  let from_ = inner.from().unwrap();
  let from = PathBuf::from(from_);
1071 1072
  let to_ = inner.to().unwrap();
  let to = PathBuf::from(to_);
1073

1074
  if let Err(e) = state.check_read(&from_) {
D
Dmitry Sharshakov 已提交
1075 1076
    return odd_future(e);
  }
1077
  if let Err(e) = state.check_write(&to_) {
1078
    return odd_future(e);
1079 1080
  }

R
Ryan Dahl 已提交
1081
  debug!("op_copy_file {} {}", from.display(), to.display());
1082
  blocking(base.sync(), move || {
1083 1084 1085 1086 1087
    // On *nix, Rust deem non-existent path as invalid input
    // See https://github.com/rust-lang/rust/issues/54800
    // Once the issue is reolved, we should remove this workaround.
    if cfg!(unix) && !from.is_file() {
      return Err(errors::new(
1088 1089
        ErrorKind::NotFound,
        "File not found".to_string(),
1090 1091 1092
      ));
    }

1093 1094 1095 1096 1097
    fs::copy(&from, &to)?;
    Ok(empty_buf())
  })
}

A
Aaron Power 已提交
1098 1099 1100 1101
macro_rules! to_seconds {
  ($time:expr) => {{
    // Unwrap is safe here as if the file is before the unix epoch
    // something is very wrong.
R
format  
Ryan Dahl 已提交
1102 1103 1104 1105
    $time
      .and_then(|t| Ok(t.duration_since(UNIX_EPOCH).unwrap().as_secs()))
      .unwrap_or(0)
  }};
A
Aaron Power 已提交
1106 1107
}

1108
#[cfg(any(unix))]
A
Andy Hayden 已提交
1109
fn get_mode(perm: &fs::Permissions) -> u32 {
1110
  perm.mode()
1111 1112 1113
}

#[cfg(not(any(unix)))]
A
Andy Hayden 已提交
1114
fn get_mode(_perm: &fs::Permissions) -> u32 {
1115
  0
1116 1117
}

S
Shiva Prasanth 已提交
1118
fn op_cwd(
1119
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
1120
  base: &msg::Base<'_>,
1121 1122
  data: deno_buf,
) -> Box<OpWithError> {
S
Shiva Prasanth 已提交
1123 1124 1125 1126 1127 1128 1129
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  Box::new(futures::future::result(|| -> OpResult {
    let path = std::env::current_dir()?;
    let builder = &mut FlatBufferBuilder::new();
    let cwd =
      builder.create_string(&path.into_os_string().into_string().unwrap());
A
Andy Hayden 已提交
1130 1131
    let inner =
      msg::CwdRes::create(builder, &msg::CwdResArgs { cwd: Some(cwd) });
S
Shiva Prasanth 已提交
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::CwdRes,
        ..Default::default()
      },
    ))
  }()))
}

R
Ryan Dahl 已提交
1144
fn op_stat(
1145
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1146
  base: &msg::Base<'_>,
1147 1148
  data: deno_buf,
) -> Box<OpWithError> {
1149
  assert_eq!(data.len(), 0);
1150
  let inner = base.inner_as_stat().unwrap();
R
Ryan Dahl 已提交
1151
  let cmd_id = base.cmd_id();
D
Dmitry Sharshakov 已提交
1152 1153
  let filename_ = inner.filename().unwrap();
  let filename = PathBuf::from(filename_);
1154
  let lstat = inner.lstat();
R
Ryan Dahl 已提交
1155

1156
  if let Err(e) = state.check_read(&filename_) {
D
Dmitry Sharshakov 已提交
1157 1158 1159
    return odd_future(e);
  }

1160
  blocking(base.sync(), move || {
R
Ryan Dahl 已提交
1161
    let builder = &mut FlatBufferBuilder::new();
R
Ryan Dahl 已提交
1162
    debug!("op_stat {} {}", filename.display(), lstat);
R
Ryan Dahl 已提交
1163
    let metadata = if lstat {
R
Ryan Dahl 已提交
1164
      fs::symlink_metadata(&filename)?
R
Ryan Dahl 已提交
1165
    } else {
R
Ryan Dahl 已提交
1166
      fs::metadata(&filename)?
R
Ryan Dahl 已提交
1167 1168
    };

1169
    let inner = msg::StatRes::create(
R
Ryan Dahl 已提交
1170
      builder,
1171
      &msg::StatResArgs {
R
Ryan Dahl 已提交
1172 1173 1174 1175 1176 1177
        is_file: metadata.is_file(),
        is_symlink: metadata.file_type().is_symlink(),
        len: metadata.len(),
        modified: to_seconds!(metadata.modified()),
        accessed: to_seconds!(metadata.accessed()),
        created: to_seconds!(metadata.created()),
A
Andy Hayden 已提交
1178
        mode: get_mode(&metadata.permissions()),
1179
        has_mode: cfg!(target_family = "unix"),
R
Ryan Dahl 已提交
1180 1181 1182
        ..Default::default()
      },
    );
A
Aaron Power 已提交
1183

R
Ryan Dahl 已提交
1184
    Ok(serialize_response(
R
Ryan Dahl 已提交
1185 1186 1187
      cmd_id,
      builder,
      msg::BaseArgs {
1188 1189
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::StatRes,
R
Ryan Dahl 已提交
1190 1191 1192
        ..Default::default()
      },
    ))
R
Ryan Dahl 已提交
1193
  })
A
Aaron Power 已提交
1194 1195
}

R
Ryan Dahl 已提交
1196
fn op_read_dir(
1197
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1198
  base: &msg::Base<'_>,
1199 1200
  data: deno_buf,
) -> Box<OpWithError> {
J
J2P 已提交
1201
  assert_eq!(data.len(), 0);
1202
  let inner = base.inner_as_read_dir().unwrap();
J
J2P 已提交
1203
  let cmd_id = base.cmd_id();
1204
  let path = String::from(inner.path().unwrap());
J
J2P 已提交
1205

1206
  if let Err(e) = state.check_read(&path) {
D
Dmitry Sharshakov 已提交
1207 1208 1209
    return odd_future(e);
  }

1210
  blocking(base.sync(), move || -> OpResult {
R
Ryan Dahl 已提交
1211
    debug!("op_read_dir {}", path);
J
J2P 已提交
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
    let builder = &mut FlatBufferBuilder::new();
    let entries: Vec<_> = fs::read_dir(Path::new(&path))?
      .map(|entry| {
        let entry = entry.unwrap();
        let metadata = entry.metadata().unwrap();
        let file_type = metadata.file_type();
        let name = builder.create_string(entry.file_name().to_str().unwrap());
        let path = builder.create_string(entry.path().to_str().unwrap());

        msg::StatRes::create(
          builder,
          &msg::StatResArgs {
            is_file: file_type.is_file(),
            is_symlink: file_type.is_symlink(),
            len: metadata.len(),
            modified: to_seconds!(metadata.modified()),
            accessed: to_seconds!(metadata.accessed()),
            created: to_seconds!(metadata.created()),
            name: Some(name),
            path: Some(path),
1232 1233
            mode: get_mode(&metadata.permissions()),
            has_mode: cfg!(target_family = "unix"),
J
J2P 已提交
1234 1235
          },
        )
R
Format  
Ryan Dahl 已提交
1236
      }).collect();
J
J2P 已提交
1237 1238

    let entries = builder.create_vector(&entries);
1239
    let inner = msg::ReadDirRes::create(
J
J2P 已提交
1240 1241 1242 1243 1244 1245 1246 1247 1248
      builder,
      &msg::ReadDirResArgs {
        entries: Some(entries),
      },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
1249 1250
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::ReadDirRes,
J
J2P 已提交
1251 1252 1253 1254 1255 1256
        ..Default::default()
      },
    ))
  })
}

R
Ryan Dahl 已提交
1257
fn op_rename(
1258
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1259
  base: &msg::Base<'_>,
1260 1261
  data: deno_buf,
) -> Box<OpWithError> {
1262
  assert_eq!(data.len(), 0);
1263 1264
  let inner = base.inner_as_rename().unwrap();
  let oldpath = PathBuf::from(inner.oldpath().unwrap());
1265 1266
  let newpath_ = inner.newpath().unwrap();
  let newpath = PathBuf::from(newpath_);
1267
  if let Err(e) = state.check_write(&newpath_) {
1268 1269
    return odd_future(e);
  }
1270
  blocking(base.sync(), move || -> OpResult {
R
Ryan Dahl 已提交
1271
    debug!("op_rename {} {}", oldpath.display(), newpath.display());
R
Ryan Dahl 已提交
1272
    fs::rename(&oldpath, &newpath)?;
R
Ryan Dahl 已提交
1273
    Ok(empty_buf())
R
Ryan Dahl 已提交
1274
  })
M
Mani Maghsoudlou 已提交
1275
}
1276

1277
fn op_link(
1278
  state: &ThreadSafeState,
1279 1280 1281 1282 1283 1284 1285 1286 1287
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_link().unwrap();
  let oldname = PathBuf::from(inner.oldname().unwrap());
  let newname_ = inner.newname().unwrap();
  let newname = PathBuf::from(newname_);

1288
  if let Err(e) = state.check_write(&newname_) {
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
    return odd_future(e);
  }

  blocking(base.sync(), move || -> OpResult {
    debug!("op_link {} {}", oldname.display(), newname.display());
    std::fs::hard_link(&oldname, &newname)?;
    Ok(empty_buf())
  })
}

R
Ryan Dahl 已提交
1299
fn op_symlink(
1300
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1301
  base: &msg::Base<'_>,
1302 1303
  data: deno_buf,
) -> Box<OpWithError> {
1304
  assert_eq!(data.len(), 0);
1305 1306 1307 1308 1309
  let inner = base.inner_as_symlink().unwrap();
  let oldname = PathBuf::from(inner.oldname().unwrap());
  let newname_ = inner.newname().unwrap();
  let newname = PathBuf::from(newname_);

1310
  if let Err(e) = state.check_write(&newname_) {
1311
    return odd_future(e);
1312 1313 1314
  }
  // TODO Use type for Windows.
  if cfg!(windows) {
1315 1316
    return odd_future(errors::new(
      ErrorKind::Other,
1317
      "Not implemented".to_string(),
1318
    ));
1319
  }
1320
  blocking(base.sync(), move || -> OpResult {
R
Ryan Dahl 已提交
1321
    debug!("op_symlink {} {}", oldname.display(), newname.display());
R
Ryan Dahl 已提交
1322 1323 1324 1325
    #[cfg(any(unix))]
    std::os::unix::fs::symlink(&oldname, &newname)?;
    Ok(empty_buf())
  })
1326
}
1327

R
Ryan Dahl 已提交
1328
fn op_read_link(
1329
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1330
  base: &msg::Base<'_>,
1331 1332
  data: deno_buf,
) -> Box<OpWithError> {
1333
  assert_eq!(data.len(), 0);
1334
  let inner = base.inner_as_readlink().unwrap();
1335
  let cmd_id = base.cmd_id();
D
Dmitry Sharshakov 已提交
1336 1337 1338
  let name_ = inner.name().unwrap();
  let name = PathBuf::from(name_);

1339
  if let Err(e) = state.check_read(&name_) {
D
Dmitry Sharshakov 已提交
1340 1341
    return odd_future(e);
  }
R
Ryan Dahl 已提交
1342

1343
  blocking(base.sync(), move || -> OpResult {
R
Ryan Dahl 已提交
1344
    debug!("op_read_link {}", name.display());
R
Ryan Dahl 已提交
1345
    let path = fs::read_link(&name)?;
1346 1347
    let builder = &mut FlatBufferBuilder::new();
    let path_off = builder.create_string(path.to_str().unwrap());
1348
    let inner = msg::ReadlinkRes::create(
1349 1350 1351 1352 1353 1354 1355 1356 1357
      builder,
      &msg::ReadlinkResArgs {
        path: Some(path_off),
      },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
1358 1359
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::ReadlinkRes,
1360 1361 1362
        ..Default::default()
      },
    ))
R
Ryan Dahl 已提交
1363
  })
1364
}
Z
ztplz 已提交
1365

A
Andy Hayden 已提交
1366
fn op_repl_start(
1367
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1368
  base: &msg::Base<'_>,
1369 1370
  data: deno_buf,
) -> Box<OpWithError> {
A
Andy Hayden 已提交
1371 1372 1373 1374 1375 1376
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_repl_start().unwrap();
  let cmd_id = base.cmd_id();
  let history_file = String::from(inner.history_file().unwrap());

  debug!("op_repl_start {}", history_file);
1377
  let history_path = repl::history_path(&state.dir, &history_file);
A
Andy Hayden 已提交
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
  let repl = repl::Repl::new(history_path);
  let resource = resources::add_repl(repl);

  let builder = &mut FlatBufferBuilder::new();
  let inner = msg::ReplStartRes::create(
    builder,
    &msg::ReplStartResArgs { rid: resource.rid },
  );
  ok_future(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::ReplStartRes,
      ..Default::default()
    },
  ))
}

fn op_repl_readline(
1398
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
1399
  base: &msg::Base<'_>,
1400 1401
  data: deno_buf,
) -> Box<OpWithError> {
A
Andy Hayden 已提交
1402 1403 1404 1405 1406 1407 1408
  assert_eq!(data.len(), 0);
  let inner = base.inner_as_repl_readline().unwrap();
  let cmd_id = base.cmd_id();
  let rid = inner.rid();
  let prompt = inner.prompt().unwrap().to_owned();
  debug!("op_repl_readline {} {}", rid, prompt);

1409
  blocking(base.sync(), move || -> OpResult {
1410 1411
    let repl = resources::get_repl(rid)?;
    let line = repl.lock().unwrap().readline(&prompt)?;
A
Andy Hayden 已提交
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429

    let builder = &mut FlatBufferBuilder::new();
    let line_off = builder.create_string(&line);
    let inner = msg::ReplReadlineRes::create(
      builder,
      &msg::ReplReadlineResArgs {
        line: Some(line_off),
      },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::ReplReadlineRes,
        ..Default::default()
      },
    ))
1430
  })
A
Andy Hayden 已提交
1431 1432
}

R
Ryan Dahl 已提交
1433
fn op_truncate(
1434
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1435
  base: &msg::Base<'_>,
1436 1437
  data: deno_buf,
) -> Box<OpWithError> {
Z
ztplz 已提交
1438 1439
  assert_eq!(data.len(), 0);

1440 1441 1442
  let inner = base.inner_as_truncate().unwrap();
  let filename = String::from(inner.name().unwrap());
  let len = inner.len();
1443

1444
  if let Err(e) = state.check_write(&filename) {
1445 1446 1447
    return odd_future(e);
  }

1448
  blocking(base.sync(), move || {
R
Ryan Dahl 已提交
1449
    debug!("op_truncate {} {}", filename, len);
Z
ztplz 已提交
1450
    let f = fs::OpenOptions::new().write(true).open(&filename)?;
A
Andy Hayden 已提交
1451
    f.set_len(u64::from(len))?;
Z
ztplz 已提交
1452 1453 1454
    Ok(empty_buf())
  })
}
1455

R
Ryan Dahl 已提交
1456
fn op_listen(
1457
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1458
  base: &msg::Base<'_>,
1459 1460
  data: deno_buf,
) -> Box<OpWithError> {
1461
  assert_eq!(data.len(), 0);
1462
  if let Err(e) = state.check_net("listen") {
1463
    return odd_future(e);
1464 1465 1466
  }

  let cmd_id = base.cmd_id();
R
Ryan Dahl 已提交
1467 1468
  let inner = base.inner_as_listen().unwrap();
  let network = inner.network().unwrap();
1469
  assert_eq!(network, "tcp");
R
Ryan Dahl 已提交
1470
  let address = inner.address().unwrap();
1471 1472

  Box::new(futures::future::result((move || {
1473
    let addr = resolve_addr(address).wait()?;
1474 1475 1476 1477 1478

    let listener = TcpListener::bind(&addr)?;
    let resource = resources::add_tcp_listener(listener);

    let builder = &mut FlatBufferBuilder::new();
R
Ryan Dahl 已提交
1479
    let inner = msg::ListenRes::create(
1480
      builder,
A
Andy Hayden 已提交
1481
      &msg::ListenResArgs { rid: resource.rid },
1482 1483 1484 1485 1486
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
R
Ryan Dahl 已提交
1487 1488
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::ListenRes,
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
        ..Default::default()
      },
    ))
  })()))
}

fn new_conn(cmd_id: u32, tcp_stream: TcpStream) -> OpResult {
  let tcp_stream_resource = resources::add_tcp_stream(tcp_stream);
  // TODO forward socket_addr to client.

  let builder = &mut FlatBufferBuilder::new();
R
Ryan Dahl 已提交
1500
  let inner = msg::NewConn::create(
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
    builder,
    &msg::NewConnArgs {
      rid: tcp_stream_resource.rid,
      ..Default::default()
    },
  );
  Ok(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
R
Ryan Dahl 已提交
1511 1512
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::NewConn,
1513 1514 1515 1516 1517
      ..Default::default()
    },
  ))
}

R
Ryan Dahl 已提交
1518
fn op_accept(
1519
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1520
  base: &msg::Base<'_>,
1521 1522
  data: deno_buf,
) -> Box<OpWithError> {
1523
  assert_eq!(data.len(), 0);
1524
  if let Err(e) = state.check_net("accept") {
1525
    return odd_future(e);
1526 1527
  }
  let cmd_id = base.cmd_id();
R
Ryan Dahl 已提交
1528 1529
  let inner = base.inner_as_accept().unwrap();
  let server_rid = inner.rid();
1530 1531

  match resources::lookup(server_rid) {
R
Ryan Dahl 已提交
1532
    None => odd_future(errors::bad_resource()),
1533
    Some(server_resource) => {
1534
      let op = tokio_util::accept(server_resource)
A
Andy Hayden 已提交
1535
        .map_err(DenoError::from)
1536 1537 1538 1539 1540 1541 1542 1543
        .and_then(move |(tcp_stream, _socket_addr)| {
          new_conn(cmd_id, tcp_stream)
        });
      Box::new(op)
    }
  }
}

R
Ryan Dahl 已提交
1544
fn op_dial(
1545
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1546
  base: &msg::Base<'_>,
1547 1548
  data: deno_buf,
) -> Box<OpWithError> {
1549
  assert_eq!(data.len(), 0);
1550
  if let Err(e) = state.check_net("dial") {
1551
    return odd_future(e);
1552 1553
  }
  let cmd_id = base.cmd_id();
R
Ryan Dahl 已提交
1554 1555
  let inner = base.inner_as_dial().unwrap();
  let network = inner.network().unwrap();
1556
  assert_eq!(network, "tcp"); // TODO Support others.
R
Ryan Dahl 已提交
1557
  let address = inner.address().unwrap();
1558

1559 1560 1561 1562 1563 1564 1565 1566
  let op =
    resolve_addr(address)
      .map_err(DenoError::from)
      .and_then(move |addr| {
        TcpStream::connect(&addr)
          .map_err(DenoError::from)
          .and_then(move |tcp_stream| new_conn(cmd_id, tcp_stream))
      });
1567 1568
  Box::new(op)
}
B
Bartek Iwańczuk 已提交
1569 1570

fn op_metrics(
1571
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1572
  base: &msg::Base<'_>,
1573 1574
  data: deno_buf,
) -> Box<OpWithError> {
B
Bartek Iwańczuk 已提交
1575 1576 1577 1578 1579 1580
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();

  let builder = &mut FlatBufferBuilder::new();
  let inner = msg::MetricsRes::create(
    builder,
1581
    &msg::MetricsResArgs::from(&state.metrics),
B
Bartek Iwańczuk 已提交
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
  );
  ok_future(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::MetricsRes,
      ..Default::default()
    },
  ))
}
B
Bartek Iwańczuk 已提交
1593 1594

fn op_resources(
1595
  _state: &ThreadSafeState,
A
Andy Hayden 已提交
1596
  base: &msg::Base<'_>,
1597 1598
  data: deno_buf,
) -> Box<OpWithError> {
B
Bartek Iwańczuk 已提交
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();

  let builder = &mut FlatBufferBuilder::new();
  let serialized_resources = table_entries();

  let res: Vec<_> = serialized_resources
    .iter()
    .map(|(key, value)| {
      let repr = builder.create_string(value);

      msg::Resource::create(
        builder,
        &msg::ResourceArgs {
A
Andy Hayden 已提交
1613
          rid: *key,
B
Bartek Iwańczuk 已提交
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
          repr: Some(repr),
        },
      )
    }).collect();

  let resources = builder.create_vector(&res);
  let inner = msg::ResourcesRes::create(
    builder,
    &msg::ResourcesResArgs {
      resources: Some(resources),
    },
  );

  ok_future(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::ResourcesRes,
      ..Default::default()
    },
  ))
}
1637 1638 1639 1640 1641 1642 1643 1644 1645

fn subprocess_stdio_map(v: msg::ProcessStdio) -> std::process::Stdio {
  match v {
    msg::ProcessStdio::Inherit => std::process::Stdio::inherit(),
    msg::ProcessStdio::Piped => std::process::Stdio::piped(),
    msg::ProcessStdio::Null => std::process::Stdio::null(),
  }
}

1646
fn op_run(
1647
  state: &ThreadSafeState,
1648 1649 1650
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
1651 1652 1653
  assert!(base.sync());
  let cmd_id = base.cmd_id();

1654
  if let Err(e) = state.check_run() {
1655 1656 1657 1658 1659 1660
    return odd_future(e);
  }

  assert_eq!(data.len(), 0);
  let inner = base.inner_as_run().unwrap();
  let args = inner.args().unwrap();
1661
  let env = inner.env().unwrap();
1662 1663
  let cwd = inner.cwd();

A
Andy Hayden 已提交
1664
  let mut c = Command::new(args.get(0));
1665 1666
  (1..args.len()).for_each(|i| {
    let arg = args.get(i);
A
Andy Hayden 已提交
1667
    c.arg(arg);
1668
  });
A
Andy Hayden 已提交
1669
  cwd.map(|d| c.current_dir(d));
1670 1671 1672 1673
  (0..env.len()).for_each(|i| {
    let entry = env.get(i);
    c.env(entry.key().unwrap(), entry.value().unwrap());
  });
1674

A
Andy Hayden 已提交
1675 1676 1677
  c.stdin(subprocess_stdio_map(inner.stdin()));
  c.stdout(subprocess_stdio_map(inner.stdout()));
  c.stderr(subprocess_stdio_map(inner.stderr()));
1678 1679

  // Spawn the command.
A
Andy Hayden 已提交
1680
  let child = match c.spawn_async() {
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
    Ok(v) => v,
    Err(err) => {
      return odd_future(err.into());
    }
  };

  let pid = child.id();
  let resources = resources::add_child(child);

  let mut res_args = msg::RunResArgs {
    rid: resources.child_rid,
    pid,
    ..Default::default()
  };

  if let Some(stdin_rid) = resources.stdin_rid {
    res_args.stdin_rid = stdin_rid;
  }
  if let Some(stdout_rid) = resources.stdout_rid {
    res_args.stdout_rid = stdout_rid;
  }
  if let Some(stderr_rid) = resources.stderr_rid {
    res_args.stderr_rid = stderr_rid;
  }

  let builder = &mut FlatBufferBuilder::new();
  let inner = msg::RunRes::create(builder, &res_args);
  ok_future(serialize_response(
    cmd_id,
    builder,
    msg::BaseArgs {
      inner: Some(inner.as_union_value()),
      inner_type: msg::Any::RunRes,
      ..Default::default()
    },
  ))
}

fn op_run_status(
1720
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1721
  base: &msg::Base<'_>,
1722 1723
  data: deno_buf,
) -> Box<OpWithError> {
1724 1725 1726 1727 1728
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_run_status().unwrap();
  let rid = inner.rid();

1729
  if let Err(e) = state.check_run() {
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
    return odd_future(e);
  }

  let future = match resources::child_status(rid) {
    Err(e) => {
      return odd_future(e);
    }
    Ok(f) => f,
  };

  let future = future.and_then(move |run_status| {
    let code = run_status.code();

    #[cfg(unix)]
    let signal = run_status.signal();
    #[cfg(not(unix))]
    let signal = None;

    code
      .or(signal)
      .expect("Should have either an exit code or a signal.");
    let got_signal = signal.is_some();

    let builder = &mut FlatBufferBuilder::new();
    let inner = msg::RunStatusRes::create(
      builder,
      &msg::RunStatusResArgs {
        got_signal,
        exit_code: code.unwrap_or(-1),
        exit_signal: signal.unwrap_or(-1),
      },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::RunStatusRes,
        ..Default::default()
      },
    ))
  });
  Box::new(future)
}
R
Ryan Dahl 已提交
1774 1775

struct GetMessageFuture {
1776
  pub state: ThreadSafeState,
R
Ryan Dahl 已提交
1777 1778 1779 1780 1781 1782 1783
}

impl Future for GetMessageFuture {
  type Item = Option<Buf>;
  type Error = ();

  fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
1784 1785 1786 1787
    let mut wc = self.state.worker_channels.lock().unwrap();
    wc.1
      .poll()
      .map_err(|err| panic!("worker_channel recv err {:?}", err))
R
Ryan Dahl 已提交
1788 1789 1790
  }
}

A
andy finch 已提交
1791
/// Get message from host as guest worker
R
Ryan Dahl 已提交
1792
fn op_worker_get_message(
1793
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1794
  base: &msg::Base<'_>,
1795 1796
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
1797 1798 1799 1800
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();

  let op = GetMessageFuture {
1801
    state: state.clone(),
R
Ryan Dahl 已提交
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
  };
  let op = op.map_err(move |_| -> DenoError { unimplemented!() });
  let op = op.and_then(move |maybe_buf| -> DenoResult<Buf> {
    debug!("op_worker_get_message");
    let builder = &mut FlatBufferBuilder::new();

    let data = maybe_buf.as_ref().map(|buf| builder.create_vector(buf));
    let inner = msg::WorkerGetMessageRes::create(
      builder,
      &msg::WorkerGetMessageResArgs { data },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(inner.as_union_value()),
        inner_type: msg::Any::WorkerGetMessageRes,
        ..Default::default()
      },
    ))
  });
  Box::new(op)
}

A
andy finch 已提交
1826
/// Post message to host as guest worker
R
Ryan Dahl 已提交
1827
fn op_worker_post_message(
1828
  state: &ThreadSafeState,
A
Andy Hayden 已提交
1829
  base: &msg::Base<'_>,
1830 1831
  data: deno_buf,
) -> Box<OpWithError> {
R
Ryan Dahl 已提交
1832 1833 1834 1835
  let cmd_id = base.cmd_id();

  let d = Vec::from(data.as_ref()).into_boxed_slice();

1836 1837 1838
  let tx = {
    let wc = state.worker_channels.lock().unwrap();
    wc.0.clone()
R
Ryan Dahl 已提交
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854
  };
  let op = tx.send(d);
  let op = op.map_err(|e| errors::new(ErrorKind::Other, e.to_string()));
  let op = op.and_then(move |_| -> DenoResult<Buf> {
    let builder = &mut FlatBufferBuilder::new();

    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        ..Default::default()
      },
    ))
  });
  Box::new(op)
}
A
andy finch 已提交
1855 1856 1857

/// Create worker as the host
fn op_create_worker(
1858
  state: &ThreadSafeState,
A
andy finch 已提交
1859 1860 1861 1862 1863 1864 1865 1866 1867
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_create_worker().unwrap();
  let specifier = inner.specifier().unwrap();

  Box::new(futures::future::result(move || -> OpResult {
1868 1869
    let parent_state = state.clone();

1870
    let child_state = ThreadSafeState::new(
A
andy finch 已提交
1871 1872
      parent_state.flags.clone(),
      parent_state.argv.clone(),
A
andy finch 已提交
1873
      op_selector_std,
1874
    );
1875 1876 1877 1878
    let rid = child_state.resource.rid;
    let name = format!("USER-WORKER-{}", specifier);

    let mut worker =
1879
      Worker::new(name, startup_data::deno_isolate_init(), child_state);
1880 1881
    js_check(worker.execute("denoMain()"));
    js_check(worker.execute("workerMain()"));
1882 1883 1884 1885 1886 1887

    let specifier_url =
      root_specifier_to_url(specifier).map_err(DenoError::from)?;

    // TODO(ry) Use execute_mod_async here.
    let result = worker.execute_mod(&specifier_url, false);
1888
    match result {
1889
      Ok(worker) => {
A
andy finch 已提交
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906
        let mut workers_tl = parent_state.workers.lock().unwrap();
        workers_tl.insert(rid, worker.shared());
        let builder = &mut FlatBufferBuilder::new();
        let msg_inner = msg::CreateWorkerRes::create(
          builder,
          &msg::CreateWorkerResArgs { rid },
        );
        Ok(serialize_response(
          cmd_id,
          builder,
          msg::BaseArgs {
            inner: Some(msg_inner.as_union_value()),
            inner_type: msg::Any::CreateWorkerRes,
            ..Default::default()
          },
        ))
      }
1907 1908 1909 1910
      Err((errors::RustOrJsError::Js(_), _worker)) => {
        Err(errors::worker_init_failed())
      }
      Err((errors::RustOrJsError::Rust(err), _worker)) => Err(err),
A
andy finch 已提交
1911 1912 1913 1914 1915 1916
    }
  }()))
}

/// Return when the worker closes
fn op_host_get_worker_closed(
1917
  state: &ThreadSafeState,
A
andy finch 已提交
1918 1919 1920 1921 1922 1923 1924
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_host_get_worker_closed().unwrap();
  let rid = inner.rid();
1925
  let state = state.clone();
A
andy finch 已提交
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947

  let shared_worker_future = {
    let workers_tl = state.workers.lock().unwrap();
    let worker = workers_tl.get(&rid).unwrap();
    worker.clone()
  };

  Box::new(shared_worker_future.then(move |_result| {
    let builder = &mut FlatBufferBuilder::new();

    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        ..Default::default()
      },
    ))
  }))
}

/// Get message from guest worker as host
fn op_host_get_message(
1948
  _state: &ThreadSafeState,
A
andy finch 已提交
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
  assert_eq!(data.len(), 0);
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_host_get_message().unwrap();
  let rid = inner.rid();

  let op = resources::get_message_from_worker(rid);
  let op = op.map_err(move |_| -> DenoError { unimplemented!() });
  let op = op.and_then(move |maybe_buf| -> DenoResult<Buf> {
    let builder = &mut FlatBufferBuilder::new();

    let data = maybe_buf.as_ref().map(|buf| builder.create_vector(buf));
    let msg_inner = msg::HostGetMessageRes::create(
      builder,
      &msg::HostGetMessageResArgs { data },
    );
    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        inner: Some(msg_inner.as_union_value()),
        inner_type: msg::Any::HostGetMessageRes,
        ..Default::default()
      },
    ))
  });
  Box::new(op)
}

/// Post message to guest worker as host
fn op_host_post_message(
1982
  _state: &ThreadSafeState,
A
andy finch 已提交
1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
  base: &msg::Base<'_>,
  data: deno_buf,
) -> Box<OpWithError> {
  let cmd_id = base.cmd_id();
  let inner = base.inner_as_host_post_message().unwrap();
  let rid = inner.rid();

  let d = Vec::from(data.as_ref()).into_boxed_slice();

  let op = resources::post_message_to_worker(rid, d);
  let op = op.map_err(|e| errors::new(ErrorKind::Other, e.to_string()));
  let op = op.and_then(move |_| -> DenoResult<Buf> {
    let builder = &mut FlatBufferBuilder::new();

    Ok(serialize_response(
      cmd_id,
      builder,
      msg::BaseArgs {
        ..Default::default()
      },
    ))
  });
  Box::new(op)
}