///|
fn runtime_host() -> @host_wasm.ExecutionFs {
@host_wasm.ExecutionFs::new()
}
///|
fn runtime_environment_host() -> @host_wasm.PortableHost {
@host_wasm.PortableHost::new()
}
///|
#cfg(target="wasm")
fn portable_exit(code : Int) -> Unit = "wasi_snapshot_preview1" "proc_exit"
///|
#cfg(any(target="wasm-gc", target="js"))
fn portable_exit(code : Int) -> Unit = "__moonbit_sys_unstable" "exit"
///|
fn runtime_exit(code : Int) -> Unit {
if code != 0 {
portable_exit(code)
}
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
priv struct SyncFileInvocation {
filesystem : @host_wasm.ReadOnlyFs
environment_host : @host_wasm.PortableHost
arguments : @cli.CliArguments
context : @project.ProjectInput
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
fn prepare_sync_file_invocation(
argv : ArrayView[String],
expected : @cli.CommandKind,
) -> SyncFileInvocation? {
let environment_host = @host_wasm.PortableHost::new()
let environment = try @application.parse_environment(environment_host) catch {
_ => return None
} noraise {
value => value
}
let arguments = try @cli.parse_arguments(argv, environment.values()) catch {
_ => return None
} noraise {
value => value
}
guard arguments.command() == expected else { return None }
let selected = match arguments.value("justfile") {
Some(value) if value != "-" => value
_ => return None
}
guard !arguments.flag("global-justfile") else { return None }
guard arguments.value("working-directory") is None else { return None }
let filesystem = @host_wasm.ReadOnlyFs::new()
let cwd = try @host.HostEnv::current_dir(environment_host) catch {
_ => return None
} noraise {
value => value
}
let selected_path = try @path.PathValue::new(selected, cwd.flavor()) catch {
_ => return None
} noraise {
value => value
}
let selected_path = if selected_path.is_absolute() {
selected_path
} else {
try cwd.join(selected_path) catch {
_ => return None
} noraise {
value => value
}
}
let metadata = try @host.HostFs::metadata(filesystem, selected_path) catch {
_ => return None
} noraise {
value => value
}
guard metadata.is_file() else { return None }
guard metadata.size() <=
@lexer.LexerLimits::default().max_source_bytes().to_int64() else {
return None
}
let context = @project.ProjectInput::new(cwd)
let context = try
@application.resolve_global_context(
filesystem, environment_host, arguments, context,
)
catch {
_ => return None
} noraise {
value => value
}
Some({ filesystem, environment_host, arguments, context, })
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
fn try_sync_file_command(
argv : ArrayView[String],
expected : @cli.CommandKind,
) -> Bool {
guard prepare_sync_file_invocation(argv, expected) is Some(prepared) else {
return false
}
let response = try
@application.execute_file_command(
prepared.filesystem,
prepared.arguments,
prepared.context,
)
catch {
_ => return false
} noraise {
value => value
}
response.exit_code() == 0 &&
response.stdout().is_empty() &&
response.stderr().is_empty()
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
fn try_sync_summary(argv : ArrayView[String]) -> String? {
guard prepare_sync_file_invocation(argv, SummaryCommand) is Some(prepared) else {
return None
}
let response = try
@application.execute_query_command(
prepared.environment_host,
prepared.arguments,
prepared.context,
)
catch {
_ => return None
} noraise {
value => value
}
guard response.exit_code() == 0 && response.stderr().is_empty() else {
return None
}
let text = @utf8.decode(response.stdout()) catch { _ => return None }
guard text.has_suffix("\n") && text != "\n" else { return None }
Some(text[:text.length() - 1].to_owned())
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
fn sync_file_command_hint(argv : ArrayView[String]) -> Int {
let mut check = false
let mut format = false
for argument in argv {
if argument == "--summary" {
return 1
}
if argument == "--check" {
check = true
} else if argument == "--fmt" {
format = true
}
}
if check {
2
} else if format {
3
} else {
0
}
}
///|
#cfg(any(target="wasm", target="wasm-gc", target="js"))
fn try_runtime_fast_path(argv : ArrayView[String]) -> ImmediateResult {
match sync_file_command_hint(argv) {
1 =>
match try_sync_summary(argv) {
Some(text) => Text(text)
None => NotHandled
}
2 =>
if try_sync_file_command(argv, CheckCommand) {
Handled
} else {
NotHandled
}
3 =>
if try_sync_file_command(argv, FormatCommand) {
Handled
} else {
NotHandled
}
_ => NotHandled
}
}