@ape-egg/vibe-compiler 4.3.10 → 4.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,6 +45,8 @@ const wireLifecycle = (child) => {
45
45
  process.on('exit', () => child.kill());
46
46
  };
47
47
 
48
+ const launcherArgs = ['--launcher', String(process.ppid)];
49
+
48
50
  const run = () => {
49
51
  const binary = getPlatformBinary();
50
52
  const binaryPath = join(nativeDir, binary);
@@ -78,7 +80,7 @@ const run = () => {
78
80
  }
79
81
 
80
82
  // Pass --cwd to tell the Rust binary the original working directory
81
- const cargoArgs = ['run', '--release', '--', '--cwd', originalCwd, ...userArgs];
83
+ const cargoArgs = ['run', '--release', '--', '--cwd', originalCwd, ...launcherArgs, ...userArgs];
82
84
 
83
85
  const cargo = spawn('cargo', cargoArgs, {
84
86
  cwd: srcDir,
@@ -103,7 +105,7 @@ const run = () => {
103
105
  }
104
106
 
105
107
  // Run the native binary (it runs in the user's cwd, so no --cwd needed)
106
- const child = spawn(binaryPath, userArgs, {
108
+ const child = spawn(binaryPath, [...launcherArgs, ...userArgs], {
107
109
  stdio: 'inherit',
108
110
  });
109
111
  wireLifecycle(child);
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ape-egg/vibe-compiler",
3
- "version": "4.3.10",
3
+ "version": "4.3.13",
4
4
  "type": "module",
5
5
  "description": "Optional Rust compiler for Vibe \u2014 pre-renders, inlines components, and optimizes iterations. The runtime never needs it.",
6
6
  "homepage": "https://vibe.korte.kim",
package/src/Cargo.lock CHANGED
@@ -1599,7 +1599,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
1599
1599
 
1600
1600
  [[package]]
1601
1601
  name = "vibe-compiler"
1602
- version = "4.3.10"
1602
+ version = "4.3.13"
1603
1603
  dependencies = [
1604
1604
  "clap",
1605
1605
  "colored",
package/src/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "vibe-compiler"
3
- version = "4.3.10"
3
+ version = "4.3.13"
4
4
  edition = "2021"
5
5
  description = "Vibe framework compiler - compiles Vibe source files into optimized output"
6
6
  authors = ["Kim Korte"]
@@ -29,7 +29,7 @@ pub fn block() -> u32 {
29
29
  }
30
30
 
31
31
  #[cfg(target_os = "macos")]
32
- pub fn release_on_exit(parent: u32, lock: PathBuf) {
32
+ pub fn release_on_exit(parent: u32, launcher: Option<u32>, lock: PathBuf) {
33
33
  let event = |ident: usize, filter: i16, fflags: u32| libc::kevent {
34
34
  ident,
35
35
  filter,
@@ -41,7 +41,11 @@ pub fn release_on_exit(parent: u32, lock: PathBuf) {
41
41
  let watched: Vec<libc::kevent> = SIGNALS
42
42
  .iter()
43
43
  .map(|&sig| event(sig as usize, libc::EVFILT_SIGNAL, 0))
44
- .chain([event(parent as usize, libc::EVFILT_PROC, libc::NOTE_EXIT)])
44
+ .chain(
45
+ std::iter::once(parent)
46
+ .chain(launcher)
47
+ .map(|pid| event(pid as usize, libc::EVFILT_PROC, libc::NOTE_EXIT)),
48
+ )
45
49
  .collect();
46
50
  let queue = unsafe { libc::kqueue() };
47
51
  let registered = unsafe {
@@ -55,13 +59,32 @@ pub fn release_on_exit(parent: u32, lock: PathBuf) {
55
59
  unsafe { libc::kevent(queue, std::ptr::null(), 0, &mut fired, 1, std::ptr::null()) };
56
60
  match fired.filter {
57
61
  libc::EVFILT_SIGNAL => release(&lock, "received shutdown signal", 128 + fired.ident as i32),
58
- _ => release(&lock, "parent process exited", 0),
62
+ _ if fired.ident == parent as usize => release(&lock, "parent process exited", 0),
63
+ _ => release(&lock, "launcher process exited", 0),
59
64
  }
60
65
  });
61
66
  }
62
67
 
68
+ #[cfg(target_os = "linux")]
69
+ fn release_on_launcher_exit(launcher: u32, lock: &PathBuf) {
70
+ match unsafe { libc::syscall(libc::SYS_pidfd_open, launcher, 0) } as libc::c_int {
71
+ -1 if std::io::Error::last_os_error().raw_os_error() == Some(libc::ESRCH) => {
72
+ release(lock, "launcher process exited", 0)
73
+ }
74
+ -1 => {}
75
+ pidfd => {
76
+ let lock = lock.clone();
77
+ std::thread::spawn(move || {
78
+ let mut exited = libc::pollfd { fd: pidfd, events: libc::POLLIN, revents: 0 };
79
+ unsafe { libc::poll(&mut exited, 1, -1) };
80
+ release(&lock, "launcher process exited", 0)
81
+ });
82
+ }
83
+ }
84
+ }
85
+
63
86
  #[cfg(all(unix, not(target_os = "macos")))]
64
- pub fn release_on_exit(parent: u32, lock: PathBuf) {
87
+ pub fn release_on_exit(parent: u32, launcher: Option<u32>, lock: PathBuf) {
65
88
  #[cfg(target_os = "linux")]
66
89
  unsafe {
67
90
  libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGHUP)
@@ -69,6 +92,8 @@ pub fn release_on_exit(parent: u32, lock: PathBuf) {
69
92
  if std::os::unix::process::parent_id() != parent {
70
93
  release(&lock, "parent process exited", 0);
71
94
  }
95
+ #[cfg(target_os = "linux")]
96
+ launcher.iter().for_each(|&pid| release_on_launcher_exit(pid, &lock));
72
97
  std::thread::spawn(move || {
73
98
  let mut sig = 0;
74
99
  unsafe { libc::sigwait(&signal_set(), &mut sig) };
@@ -82,4 +107,4 @@ pub fn block() -> u32 {
82
107
  }
83
108
 
84
109
  #[cfg(not(unix))]
85
- pub fn release_on_exit(_parent: u32, _lock: PathBuf) {}
110
+ pub fn release_on_exit(_parent: u32, _launcher: Option<u32>, _lock: PathBuf) {}
@@ -440,12 +440,12 @@ fn restart_with_fresh_config(lock: WatchLock) -> ! {
440
440
  }
441
441
 
442
442
  /// Start watching for file changes
443
- pub fn watch(config: Config, verbose: bool) -> std::result::Result<(), Box<dyn std::error::Error>> {
443
+ pub fn watch(config: Config, verbose: bool, launcher: Option<u32>) -> std::result::Result<(), Box<dyn std::error::Error>> {
444
444
  // Held for the watcher's whole lifetime; a second watcher on the same
445
445
  // output exits loudly instead of silently racing this one.
446
446
  let parent = shutdown::block();
447
447
  let _watch_lock = WatchLock::acquire(&config.output)?;
448
- shutdown::release_on_exit(parent, _watch_lock.path.clone());
448
+ shutdown::release_on_exit(parent, launcher, _watch_lock.path.clone());
449
449
 
450
450
  println!("{}", "Building dependency graph...".cyan());
451
451
  let mut graph = build_dependency_graph(&config)?;
package/src/main.rs CHANGED
@@ -98,6 +98,10 @@ struct Args {
98
98
  /// Compile the pages tree to SPA output: fragments + route table + shell
99
99
  #[arg(long)]
100
100
  spa: bool,
101
+
102
+ /// Pid of the process that launched the wrapper; --watch also exits when it does
103
+ #[arg(long, hide = true)]
104
+ launcher: Option<u32>,
101
105
  }
102
106
 
103
107
  fn main() {
@@ -256,7 +260,7 @@ fn main() {
256
260
 
257
261
  // Handle watch mode
258
262
  if args.watch {
259
- if let Err(e) = compiler::watcher::watch(config, args.verbose) {
263
+ if let Err(e) = compiler::watcher::watch(config, args.verbose, args.launcher) {
260
264
  eprintln!("{}: {}", "Error".red(), e);
261
265
  std::process::exit(1);
262
266
  }