aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Derrick Farris <mr.dcfarris@gmail.com> 2023-02-22 14:39:40 -0600
committerGravatar GitHub <noreply@github.com> 2023-02-22 12:39:40 -0800
commit9be68ac2350b965037f408ce4d47c3b9d9a76b63 (patch)
tree6901760d1be141ae97a55910d411fcb4beada773
parentee60a5c55cdafc96268efdebb73aedb3a2ac88fa (diff)
downloadbun-9be68ac2350b965037f408ce4d47c3b9d9a76b63.tar.gz
bun-9be68ac2350b965037f408ce4d47c3b9d9a76b63.tar.zst
bun-9be68ac2350b965037f408ce4d47c3b9d9a76b63.zip
fix(child_process): match Node's promisified exec fn (#2128)
-rw-r--r--src/bun.js/child_process.exports.js115
-rw-r--r--test/bun.js/child_process.test.ts12
2 files changed, 84 insertions, 43 deletions
diff --git a/src/bun.js/child_process.exports.js b/src/bun.js/child_process.exports.js
index afb427461..fefacd708 100644
--- a/src/bun.js/child_process.exports.js
+++ b/src/bun.js/child_process.exports.js
@@ -6,9 +6,47 @@ const {
const {
constants: { signals },
} = import.meta.require("node:os");
+const { promisify } = import.meta.require("node:util");
const { ArrayBuffer } = import.meta.primordials;
+var Uint8Array = globalThis.Uint8Array;
+var String = globalThis.String;
+var Object = globalThis.Object;
+var Buffer = globalThis.Buffer;
+var Promise = globalThis.Promise;
+
+var PromiseAll = Promise.all;
+
+var ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;
+var ObjectCreate = Object.create;
+var ObjectAssign = Object.assign;
+var ObjectDefineProperty = Object.defineProperty;
+var BufferConcat = Buffer.concat;
+var BufferIsEncoding = Buffer.isEncoding;
+
+var kEmptyObject = ObjectCreate(null);
+
+var ArrayPrototypePush = Array.prototype.push;
+var ArrayPrototypeReduce = Array.prototype.reduce;
+var ArrayPrototypeFilter = Array.prototype.filter;
+var ArrayPrototypeJoin = Array.prototype.join;
+var ArrayPrototypeMap = Array.prototype.map;
+var ArrayPrototypeIncludes = Array.prototype.includes;
+var ArrayPrototypeSlice = Array.prototype.slice;
+var ArrayPrototypeUnshift = Array.prototype.unshift;
+var ArrayIsArray = Array.isArray;
+
+// var ArrayBuffer = ArrayBuffer;
+var ArrayBufferIsView = ArrayBuffer.isView;
+
+var NumberIsInteger = Number.isInteger;
+var MathAbs = Math.abs;
+
+var StringPrototypeToUpperCase = String.prototype.toUpperCase;
+var StringPrototypeIncludes = String.prototype.includes;
+var Uint8ArrayPrototypeIncludes = Uint8Array.prototype.includes;
+
const MAX_BUFFER = 1024 * 1024;
// General debug vs tracking stdio streams. Useful for stream debugging in particular
@@ -34,9 +72,8 @@ if (__TRACK_STDIO__) {
// 3. ChildProcess "class"
// 4. ChildProcess helpers
// 5. Validators
-// 6. Primordials
-// 7. Random utilities
-// 8. Node errors / error polyfills
+// 6. Random utilities
+// 7. Node errors / error polyfills
// TODO:
// Port rest of node tests
@@ -456,6 +493,35 @@ export function exec(command, options, callback) {
return execFile(opts.file, opts.options, opts.callback);
}
+const customPromiseExecFunction = orig => {
+ return (...args) => {
+ let resolve;
+ let reject;
+ const promise = new Promise((res, rej) => {
+ resolve = res;
+ reject = rej;
+ });
+
+ promise.child = orig(...args, (err, stdout, stderr) => {
+ if (err !== null) {
+ err.stdout = stdout;
+ err.stderr = stderr;
+ reject(err);
+ } else {
+ resolve({ stdout, stderr });
+ }
+ });
+
+ return promise;
+ };
+};
+
+ObjectDefineProperty(exec, promisify.custom, {
+ __proto__: null,
+ enumerable: false,
+ value: customPromiseExecFunction(exec),
+});
+
/**
* Spawns a new process synchronously using the given `file`.
* @param {string} file
@@ -685,7 +751,7 @@ function normalizeExecFileArgs(file, args, options, callback) {
}
if (options == null) {
- options = {};
+ options = kEmptyObject;
}
if (callback != null) {
@@ -1439,49 +1505,12 @@ function getValidatedPath(fileURLOrPath, propName = "path") {
return path;
}
-//------------------------------------------------------------------------------
-// Section 6. Primordials
-//------------------------------------------------------------------------------
-var Uint8Array = globalThis.Uint8Array;
-var String = globalThis.String;
-var Object = globalThis.Object;
-var Buffer = globalThis.Buffer;
-var Promise = globalThis.Promise;
-
-var PromiseAll = Promise.all;
-
-var ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;
-var ObjectCreate = Object.create;
-var ObjectAssign = Object.assign;
-var BufferConcat = Buffer.concat;
-var BufferIsEncoding = Buffer.isEncoding;
-
-var ArrayPrototypePush = Array.prototype.push;
-var ArrayPrototypeReduce = Array.prototype.reduce;
-var ArrayPrototypeFilter = Array.prototype.filter;
-var ArrayPrototypeJoin = Array.prototype.join;
-var ArrayPrototypeMap = Array.prototype.map;
-var ArrayPrototypeIncludes = Array.prototype.includes;
-var ArrayPrototypeSlice = Array.prototype.slice;
-var ArrayPrototypeUnshift = Array.prototype.unshift;
-var ArrayIsArray = Array.isArray;
-
-// var ArrayBuffer = ArrayBuffer;
-var ArrayBufferIsView = ArrayBuffer.isView;
-
-var NumberIsInteger = Number.isInteger;
-var MathAbs = Math.abs;
-
-var StringPrototypeToUpperCase = String.prototype.toUpperCase;
-var StringPrototypeIncludes = String.prototype.includes;
-var Uint8ArrayPrototypeIncludes = Uint8Array.prototype.includes;
-
function isUint8Array(value) {
return typeof value === "object" && value !== null && value instanceof Uint8Array;
}
//------------------------------------------------------------------------------
-// Section 7. Random utilities
+// Section 6. Random utilities
//------------------------------------------------------------------------------
function isURLInstance(fileURLOrPath) {
@@ -1494,7 +1523,7 @@ function toPathIfFileURL(fileURLOrPath) {
}
//------------------------------------------------------------------------------
-// Section 8. Node errors / error polyfills
+// Section 7. Node errors / error polyfills
//------------------------------------------------------------------------------
var Error = globalThis.Error;
var TypeError = globalThis.TypeError;
diff --git a/test/bun.js/child_process.test.ts b/test/bun.js/child_process.test.ts
index 7c1315baf..7f2c6b383 100644
--- a/test/bun.js/child_process.test.ts
+++ b/test/bun.js/child_process.test.ts
@@ -2,6 +2,7 @@ import { describe, it as it_, expect as expect_ } from "bun:test";
import { gcTick } from "gc";
import { ChildProcess, spawn, execFile, exec, fork, spawnSync, execFileSync, execSync } from "node:child_process";
import { tmpdir } from "node:os";
+import { promisify } from "node:util";
const expect: typeof expect_ = (actual: unknown) => {
gcTick();
@@ -263,6 +264,17 @@ describe("exec()", () => {
});
expect(SEMVER_REGEX.test(result.toString().trim())).toBe(true);
});
+
+ it("should return an object w/ stdout and stderr when promisified", async () => {
+ const result = await promisify(exec)("bun -v");
+ expect(typeof result).toBe("object");
+ expect(typeof result.stdout).toBe("string");
+ expect(typeof result.stderr).toBe("string");
+
+ const { stdout, stderr } = result;
+ expect(SEMVER_REGEX.test(stdout.trim())).toBe(true);
+ expect(stderr.trim()).toBe("");
+ });
});
describe("fork()", () => {