New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fromCallback with multiArgs throws an error when callback is called without arguments. #1063

Closed
an-sh opened this Issue Apr 1, 2016 · 1 comment

Comments

Projects
None yet
2 participants
@an-sh

an-sh commented Apr 1, 2016

Currently when fromCallback (with multiArgs : true) callback function is
called without any arguments, like cb(), bluebird throws the following error:

Unhandled rejection RangeError: Invalid array length
    at /app/available_modules/1459505274000/bluebird/js/release/nodeback.js:44:53
    at fn1 (eval at <anonymous> (/app/index.js:715:19), <anonymous>:3:3)
    at capture.Promise.fromCallback.multiArgs (eval at <anonymous> (/app/index.js:715:19), <anonymous>:36:7)
    at tryCatcher (/app/available_modules/1459505274000/bluebird/js/release/util.js:16:23)
    at Function.Promise.fromNode.Promise.fromCallback (/app/available_modules/1459505274000/bluebird/js/release/promise.js:176:30)
    at eval (eval at <anonymous> (/app/index.js:715:19), <anonymous>:35:24)
    at GeneratorFunctionPrototype.next (native)
    at /app/index.js:573:32
    at GeneratorFunctionPrototype.next (native)
    at iterate (/app/index.js:587:77)
    at module.exports (/app/index.js:601:19)
    at eval (/app/index.js:697:5)
    at Object.<anonymous> (/app/index.js:710:3)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)

This doesn't happen neither if callback is called like cb(null), nor
when multiArgs is false.

Here is a demonstration snippet:
https://tonicdev.com/56fd394c96866f11009cfcd1/56fe47f6a404b41100ae1aa5

@HCanber

This comment has been minimized.

Show comment
Hide comment
@HCanber

HCanber Apr 1, 2016

I was about to report the same bug for bluebird@3.3.4.

Here is a shorter working example, this time using promisify

const fn = Promise.promisify(cb => cb(), { multiArgs: true })
fn()

The problem in nodeback.js is because INLINE_SLICE cannot handle the case when arguments is empty, i.e. has length 0:
INLINE_SLICE(args, arguments, 1)

The generated code is:

var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}; 

i.e. it's trying to create an array of size -1 which causes a RangeError: Invalid array length.

Two possible solutions: INLINE_SLICE is changed or nodeback.js is updated:

function nodebackForPromise(promise, multiArgs) {
    return function(err, value) {
        if (promise === null) return;
        if (err) {
            var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
            promise._attachExtraTrace(wrapped);
            promise._reject(wrapped);
        } else if (!multiArgs) {
            promise._fulfill(value);
+       } else if (arguments.length === 0) {
+           promise._fulfill();
        } else {
            INLINE_SLICE(args, arguments, 1);
            promise._fulfill(args);
        }
        promise = null;
    };
}

HCanber commented Apr 1, 2016

I was about to report the same bug for bluebird@3.3.4.

Here is a shorter working example, this time using promisify

const fn = Promise.promisify(cb => cb(), { multiArgs: true })
fn()

The problem in nodeback.js is because INLINE_SLICE cannot handle the case when arguments is empty, i.e. has length 0:
INLINE_SLICE(args, arguments, 1)

The generated code is:

var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}; 

i.e. it's trying to create an array of size -1 which causes a RangeError: Invalid array length.

Two possible solutions: INLINE_SLICE is changed or nodeback.js is updated:

function nodebackForPromise(promise, multiArgs) {
    return function(err, value) {
        if (promise === null) return;
        if (err) {
            var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
            promise._attachExtraTrace(wrapped);
            promise._reject(wrapped);
        } else if (!multiArgs) {
            promise._fulfill(value);
+       } else if (arguments.length === 0) {
+           promise._fulfill();
        } else {
            INLINE_SLICE(args, arguments, 1);
            promise._fulfill(args);
        }
        promise = null;
    };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment