Skip to content

isPlainObject() throws TypeError in v2.2.1, but not in v1.11.1 #2982

@codeworrior

Description

@codeworrior

Hi,
when migrating our code from jQuery 1.11.1 to jQuery 2.2.1, we found a difference between the jQuery.isPlainObject implementations in the two versions. This difference also affects other jQuery methods that internally call isPlainObject, like jQuery.extend.

See https://jsfiddle.net/tjmgfjg4/1/ for a reduced example with jQuery.extend.

The reason seems to be that 3dccf62 removed the try ... catch around the following check in isPlainObject:

        if ( obj.constructor &&
                !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
            return false;
        }

When isPlainObject is called for an object which has a constructor property with a non-falsy, non-function value, it now throws a TypeError ("Cannot convert undefined or null to object").

I understand that using a property constructor with a value other than the original constructor function is somewhat 'unusual' and not best practice. But as far as I can see, this is not prohibited by an Ecmascript spec (up to and including ES2015). I also understand that it is discussable whether such objects should be reported as plain or not. But running into a TypeError seems quite unexpected.

Adding the try ... catch back might not be the best way to fix this. But maybe the check could be made more robust by some other mean, e.g. adding another condition (motivated by the concrete error)

        if ( obj.constructor &&
                typeof obj.constructor.prototype === 'object' &&
                !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
            return false;
        }

or by checking whether obj.constructor is of type function (motivated by the original intention: check whether the standard constructorbacklink points to Object)

        if ( typeof obj.constructor === 'function' &&
                !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
            return false;
        }

Please let me know your thoughts about this: regression or valid simplification?

Kind Regards, cw

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions