Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
627 changes: 42 additions & 585 deletions src/runtime/shell/Builtin.rs

Large diffs are not rendered by default.

452 changes: 396 additions & 56 deletions src/runtime/shell/IO.rs

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/runtime/shell/builtin/basename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ impl Basename {
};

Self::state_mut(interp, cmd).state = State::Done;
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
Self::state_mut(interp, cmd).buf = buf;
let owned = Self::state_mut(interp, cmd).buf.clone();
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
return interp
.as_cmd(cmd)
.io
.stdout
.enqueue(child, &owned, safeguard);
}
Expand Down
33 changes: 16 additions & 17 deletions src/runtime/shell/builtin/cat.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::sync::Arc;

use crate::shell::ExitCode;
use crate::shell::builtin::{Builtin, BuiltinIO, BuiltinInput, BuiltinState, IoKind, Kind};
use crate::shell::builtin::{Builtin, BuiltinState, IoKind, Kind};
use crate::shell::interpreter::{
FlagParser, Interpreter, NodeId, ParseFlagResult, parse_flags, shell_openat, unsupported_flag,
};
use crate::shell::io::{CmdIn, CmdOut};
use crate::shell::io_reader::{ChildPtr as ReaderChildPtr, IOReader, ReaderTag};
use crate::shell::io_writer::{ChildPtr, WriterTag};
use crate::shell::yield_::Yield;
Expand Down Expand Up @@ -103,12 +104,10 @@ impl Cat {
buf: &[u8],
exit_code: ExitCode,
) -> Yield {
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
Self::state_mut(interp, cmd).state = CatState::WaitingWriteErr;
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stderr
.enqueue(child, buf, safeguard);
return interp.as_cmd(cmd).io.stderr.enqueue(child, buf, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stderr, buf);
Builtin::done(interp, cmd, exit_code)
Expand Down Expand Up @@ -136,7 +135,7 @@ impl Cat {
Branch::Stdin => {
// Stdin doesn't need IO (captured/ignored): read it all
// synchronously and write straight to stdout.
let stdin_needs_io = Builtin::of(interp, cmd).stdin.needs_io();
let stdin_needs_io = interp.as_cmd(cmd).io.stdin.needs_io();
if !stdin_needs_io {
if let CatState::ExecStdin { in_done, .. } =
&mut Self::state_mut(interp, cmd).state
Expand All @@ -146,11 +145,9 @@ impl Cat {
// Copy stdin bytes so the &mut on `stdout`/`write_no_io`
// doesn't overlap a borrow of `stdin`.
let buf = Builtin::read_stdin_no_io(interp, cmd).to_vec();
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stdout
.enqueue(child, &buf, safeguard);
return interp.as_cmd(cmd).io.stdout.enqueue(child, &buf, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stdout, &buf);
return Builtin::done(interp, cmd, 0);
Expand All @@ -159,8 +156,8 @@ impl Cat {
// out of `stdin` so we hold no borrow of `interp` across
// `start()` (which may re-enter via the raw interp backref).
let interp_ptr: *mut Interpreter = interp.as_ctx_ptr();
let reader = match &Builtin::of(interp, cmd).stdin {
BuiltinInput::Fd(r) => Arc::clone(r),
let reader = match &interp.as_cmd(cmd).io.stdin {
CmdIn::Fd(r) => Arc::clone(r),
_ => unreachable!("needs_io() returned true"),
};
reader.set_interp(interp_ptr);
Expand Down Expand Up @@ -260,7 +257,7 @@ impl Cat {
*st_errno = errno;
let was_done = core::mem::replace(in_done, true);
if !was_done {
if let BuiltinInput::Fd(r) = &Builtin::of(interp, cmd).stdin {
if let CmdIn::Fd(r) = &interp.as_cmd(cmd).io.stdin {
r.remove_reader(rchild);
}
}
Expand Down Expand Up @@ -320,14 +317,16 @@ impl Cat {
remove: &mut bool,
) -> Yield {
*remove = false;
let stdout_needs_io = Builtin::of(interp, cmd).stdout.needs_io();
let stdout_needs_io = interp.as_cmd(cmd).io.stdout.needs_io();
match &mut Self::state_mut(interp, cmd).state {
CatState::ExecStdin { chunks_queued, .. }
| CatState::ExecFilepathArgs { chunks_queued, .. } => {
if let Some(safeguard) = stdout_needs_io {
*chunks_queued += 1;
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
return interp
.as_cmd(cmd)
.io
.stdout
.enqueue(child, chunk, safeguard);
}
Expand All @@ -344,7 +343,7 @@ impl Cat {
err: Option<bun_sys::SystemError>,
) -> Yield {
let errno: ExitCode = err.map(|e| e.get_errno() as ExitCode).unwrap_or(0);
let stdout_needs_io = Builtin::of(interp, cmd).stdout.needs_io().is_some();
let stdout_needs_io = interp.as_cmd(cmd).io.stdout.needs_io().is_some();
let mut cancel = false;
let step = match &mut Self::state_mut(interp, cmd).state {
CatState::ExecStdin {
Expand Down Expand Up @@ -396,7 +395,7 @@ impl Cat {
};
if cancel {
let wchild = ChildPtr::new(cmd, WriterTag::Builtin);
if let BuiltinIO::Fd(fd) = &Builtin::of(interp, cmd).stdout {
if let CmdOut::Fd(fd) = &interp.as_cmd(cmd).io.stdout {
fd.writer.cancel_chunks(wchild);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/shell/builtin/cd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ impl Cd {
args: core::fmt::Arguments<'_>,
) -> Yield {
Self::state_mut(interp, cmd).state = State::WaitingIo;
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd).stderr.enqueue_fmt(
return interp.as_cmd(cmd).io.stderr.enqueue_fmt(
child,
Some(Kind::Cd),
args,
Expand Down
12 changes: 8 additions & 4 deletions src/runtime/shell/builtin/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,15 @@ impl OutputTaskVTable for Cp {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
// Stash so on_io_writer_chunk can route to the OutputTask state
// machine and reclaim the box (stopgap for missing WriterTag).
Self::state_mut(interp, cmd).output_queue.push_back(child);
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stderr
.enqueue(childptr, errbuf, safeguard),
);
Expand All @@ -365,12 +367,14 @@ impl OutputTaskVTable for Cp {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
Self::state_mut(interp, cmd).output_queue.push_back(child);
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
let buf = output.slice().to_vec();
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stdout
.enqueue(childptr, &buf, safeguard),
);
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/shell/builtin/dirname.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Dirname {
return Self::fail(interp, cmd, b"usage: dirname string\n");
}

let stdout_needs_io = bltn.stdout.needs_io();
let stdout_needs_io = interp.as_cmd(cmd).io.stdout.needs_io();
let mut buf = Vec::new();
for i in 0..argc {
let path = bltn.arg_bytes(i);
Expand All @@ -40,7 +40,9 @@ impl Dirname {
Self::state_mut(interp, cmd).buf = buf;
let owned = Self::state_mut(interp, cmd).buf.clone();
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
return interp
.as_cmd(cmd)
.io
.stdout
.enqueue(child, &owned, safeguard);
}
Expand Down
6 changes: 2 additions & 4 deletions src/runtime/shell/builtin/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,11 @@ impl Echo {
};
Self::state_mut(interp, cmd).output = output;

if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
Self::state_mut(interp, cmd).state = State::WaitingIo;
let buf = Self::state_mut(interp, cmd).output.clone();
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stdout
.enqueue(child, &buf, safeguard);
return interp.as_cmd(cmd).io.stdout.enqueue(child, &buf, safeguard);
}
let buf = Self::state_mut(interp, cmd).output.clone();
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stdout, &buf);
Expand Down
6 changes: 2 additions & 4 deletions src/runtime/shell/builtin/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,10 @@ impl Export {
buf.push(b'\n');
}

if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
Self::state_mut(interp, cmd).state = State::WaitingIo;
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stdout
.enqueue(child, &buf, safeguard);
return interp.as_cmd(cmd).io.stdout.enqueue(child, &buf, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stdout, &buf);
Builtin::done(interp, cmd, 0)
Expand Down
12 changes: 8 additions & 4 deletions src/runtime/shell/builtin/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,15 +284,17 @@ impl OutputTaskVTable for Ls {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
// Stash so on_io_writer_chunk can route to the OutputTask state
// machine and reclaim the box (stopgap for missing WriterTag).
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_queue.push_back(child);
}
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stderr
.enqueue(childptr, errbuf, safeguard),
);
Expand All @@ -314,14 +316,16 @@ impl OutputTaskVTable for Ls {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_queue.push_back(child);
}
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
let buf = output.slice().to_vec();
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stdout
.enqueue(childptr, &buf, safeguard),
);
Expand Down
12 changes: 8 additions & 4 deletions src/runtime/shell/builtin/mkdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ impl OutputTaskVTable for Mkdir {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
// OutputTask has no `WriterTag` of its own (it is not directly
// dispatchable as an IOWriter child), so the enqueue is tagged
// `WriterTag::Builtin` and `child` is stashed on `output_queue`;
Expand All @@ -203,7 +203,9 @@ impl OutputTaskVTable for Mkdir {
}
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stderr
.enqueue(childptr, errbuf, safeguard),
);
Expand All @@ -227,7 +229,7 @@ impl OutputTaskVTable for Mkdir {
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
exec.output_waiting += 1;
}
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
// See write_err — stash `child` so the chunk callback routes to
// OutputTask::on_io_writer_chunk.
if let State::Exec(exec) = &mut Self::state_mut(interp, cmd).state {
Expand All @@ -236,7 +238,9 @@ impl OutputTaskVTable for Mkdir {
let childptr = ChildPtr::new(cmd, WriterTag::Builtin);
let buf = output.slice().to_vec();
return Some(
Builtin::of_mut(interp, cmd)
interp
.as_cmd(cmd)
.io
.stdout
.enqueue(childptr, &buf, safeguard),
);
Expand Down
6 changes: 2 additions & 4 deletions src/runtime/shell/builtin/mv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,10 @@ impl Mv {
buf: &[u8],
exit_code: ExitCode,
) -> Yield {
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
Self::state_mut(interp, cmd).state = MvState::WaitingWriteErr { exit_code };
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stderr
.enqueue(child, buf, safeguard);
return interp.as_cmd(cmd).io.stderr.enqueue(child, buf, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stderr, buf);
Builtin::done(interp, cmd, exit_code)
Expand Down
12 changes: 4 additions & 8 deletions src/runtime/shell/builtin/pwd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@ impl Pwd {
pub(crate) fn start(interp: &Interpreter, cmd: NodeId) -> Yield {
if !Builtin::of(interp, cmd).args_slice().is_empty() {
let msg: &[u8] = b"pwd: too many arguments\n";
if let Some(safeguard) = Builtin::of(interp, cmd).stderr.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stderr.needs_io() {
Self::state_mut(interp, cmd).state = State::WaitingIo {
kind: WaitKind::Stderr,
};
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stderr
.enqueue(child, msg, safeguard);
return interp.as_cmd(cmd).io.stderr.enqueue(child, msg, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stderr, msg);
return Builtin::done(interp, cmd, 1);
Expand All @@ -47,14 +45,12 @@ impl Pwd {
v.push(b'\n');
v
};
if let Some(safeguard) = Builtin::of(interp, cmd).stdout.needs_io() {
if let Some(safeguard) = interp.as_cmd(cmd).io.stdout.needs_io() {
Self::state_mut(interp, cmd).state = State::WaitingIo {
kind: WaitKind::Stdout,
};
let child = ChildPtr::new(cmd, WriterTag::Builtin);
return Builtin::of_mut(interp, cmd)
.stdout
.enqueue(child, &cwd, safeguard);
return interp.as_cmd(cmd).io.stdout.enqueue(child, &cwd, safeguard);
}
let _ = Builtin::write_no_io(interp, cmd, IoKind::Stdout, &cwd);
Self::state_mut(interp, cmd).state = State::Done;
Expand Down
Loading
Loading