Commit f533385

Anton Golub <antongolub@antongolub.com>
2025-06-22 15:32:27
chore: impr rejections handling in `$` literals
1 parent cffa787
Changed files (4)
build/cli.js
build/core.cjs
@@ -548,21 +548,14 @@ var _ProcessPromise = class _ProcessPromise extends Promise {
           self._command = _cmd;
           ctx.cmd = self.fullCmd;
           cb();
-        }, (err) => {
-          ctx.spawn = () => {
-            throw err;
-          };
-          cb();
+        }, (error) => {
+          var _a3, _b3;
+          (_b3 = (_a3 = ctx.on).end) == null ? void 0 : _b3.call(_a3, { error, status: null, signal: null, duration: 0, ctx }, ctx);
         })) || cb();
       },
       on: {
         start: () => {
-          $2.log({
-            kind: "cmd",
-            cmd: self.cmd,
-            verbose: self.isVerbose(),
-            id
-          });
+          $2.log({ kind: "cmd", cmd: self.cmd, verbose: self.isVerbose(), id });
           !sync && timeout && self.timeout(timeout, timeoutSignal);
         },
         stdout: (data) => {
src/core.ts
@@ -315,20 +315,13 @@ export class ProcessPromise extends Promise<ProcessOutput> {
           self._command = _cmd
           ctx.cmd = self.fullCmd
           cb()
-        }, err => {
-          ctx.spawn = () => { throw err }
-          cb()
+        }, error => {
+          ctx.on.end?.({error, status: null, signal: null, duration: 0, ctx} as Parameters<typeof ctx.on.end>[0], ctx)
         }) || cb()
       },
       on: {
         start: () => {
-          $.log({
-            kind: 'cmd',
-            cmd: self.cmd,
-            verbose: self.isVerbose(),
-            id,
-          })
-
+          $.log({ kind: 'cmd', cmd: self.cmd, verbose: self.isVerbose(), id })
           !sync && timeout && self.timeout(timeout, timeoutSignal)
         },
         stdout: (data) => {
test/core.test.js
@@ -114,16 +114,35 @@ describe('core', () => {
     })
 
     test('accepts thenable arguments', async () => {
-      const p1 = $`echo foo`
-      const arg = new Promise((resolve) => {
-        setTimeout(() => resolve(['thenable', 'args']), 20)
-      })
-      const p2 = $`echo ${arg} ${p1}`
-      assert(p2.cmd instanceof Promise)
+      const a1 = $`echo foo`
+      const a2 = new Promise((res) => setTimeout(res, 10, ['bar', 'baz']))
+      const a3 = new Promise((_, rej) => setTimeout(rej, 20, 'failure'))
+
+      const p1 = $`echo ${a1} ${a2}`
+      assert(p1.cmd instanceof Promise)
+      const o1 = await p1
+      assert(o1 instanceof ProcessOutput)
+      assert.equal(o1.stdout.trim(), 'foo bar baz')
+      assert.equal(p1.cmd, 'echo foo bar baz')
+
+      try {
+        await $`echo ${a3}`
+      } catch (e) {
+        assert.ok(e instanceof ProcessOutput)
+        assert.equal(e.exitCode, null)
+        assert.equal(e.cause, 'failure')
+      }
+
+      try {
+        await $`echo ${$`exit 1`}`
+      } catch (e) {
+        assert.ok(e instanceof ProcessOutput)
+        assert.ok(e.cause instanceof ProcessOutput)
+        assert.equal(e.exitCode, null)
+        assert.equal(e.cause.exitCode, 1)
+      }
 
-      const o = await p2
-      assert.equal(o.stdout.trim(), 'thenable args foo')
-      assert.equal(p2.cmd, 'echo thenable args foo')
+      await Promise.allSettled([a3])
     })
 
     test.skip('handles multiline literals', async () => {