diff --git a/lib/utils.js b/lib/utils.js index a5ed039..e9a45ff 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -136,6 +136,27 @@ const isPlainObject = (val) => { return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(toStringTag in val) && !(iterator in val); } +/** + * Determine if a value is an empty object (safely handles Buffers) + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is an empty object, otherwise false + */ +const isEmptyObject = (val) => { + // Early return for non-objects or Buffers to prevent RangeError + if (!isObject(val) || isBuffer(val)) { + return false; + } + + try { + return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype; + } catch (e) { + // Fallback for any other objects that might cause RangeError with Object.keys() + return false; + } +} + /** * Determine if a value is a Date * @@ -258,6 +279,11 @@ function forEach(obj, fn, {allOwnKeys = false} = {}) { fn.call(null, obj[i], i, obj); } } else { + // Buffer check + if (isBuffer(obj)) { + return; + } + // Iterate over object keys const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj); const len = keys.length; @@ -271,6 +297,10 @@ function forEach(obj, fn, {allOwnKeys = false} = {}) { } function findKey(obj, key) { + if (isBuffer(obj)){ + return null; + } + key = key.toLowerCase(); const keys = Object.keys(obj); let i = keys.length; @@ -624,6 +654,11 @@ const toJSONObject = (obj) => { return; } + //Buffer check + if (isBuffer(source)) { + return source; + } + if(!('toJSON' in source)) { stack[i] = source; const target = isArray(source) ? [] : {}; @@ -695,6 +730,7 @@ export default { isBoolean, isObject, isPlainObject, + isEmptyObject, isReadableStream, isRequest, isResponse, diff --git a/test/unit/utils/utils.js b/test/unit/utils/utils.js index 8d40250..76eebcc 100644 --- a/test/unit/utils/utils.js +++ b/test/unit/utils/utils.js @@ -80,4 +80,38 @@ describe('utils', function (){ assert.strictEqual(JSON.stringify(jsonObject), JSON.stringify({x: 1, y:2, obj: {ok: 1}})) }); }); + + describe('Buffer RangeError Fix', function () { + it('should handle large Buffer in isEmptyObject without RangeError', function () { + // Create a big buffer that used to cause the error + const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB + + // This used to throw: RangeError: Invalid array length + // Now it should work fine + const result = utils.isEmptyObject(largeBuffer); + + // Buffer should not be considered an empty object + assert.strictEqual(result, false); + }); + + it('should handle large Buffer in forEach without RangeError', function () { + const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB + let count = 0; + + // This should skip the buffer (not iterate through it) + utils.forEach(largeBuffer, () => count++); + + // Count should be 0 because forEach skips Buffers + assert.strictEqual(count, 0); + }); + + it('should handle large Buffer in findKey without RangeError', function () { + const largeBuffer = Buffer.alloc(1024 * 1024 * 200); // 200MB + + // Should return null for Buffers + const result = utils.findKey(largeBuffer, 'test'); + + assert.strictEqual(result, null); + }); + }); });