api.jquery.com icon indicating copy to clipboard operation
api.jquery.com copied to clipboard

jQuery.isPlainObject( { ... } ) can be tricked by manipulating Symbol.toStringTag

Open Andrew-Cottrell opened this issue 4 years ago • 6 comments
trafficstars

The documentation for isPlainObject indicates the following evaluates to true, but in jQuery v3.5.1 it evaluates to false.

jQuery.isPlainObject( { [Symbol.toStringTag]: "Tag" } );

I suggest the documentation be changed to clarify the behaviour when an otherwise plain object has a [Symbol.toStringTag] property unequal to "Object".

Andrew-Cottrell avatar Feb 02 '21 19:02 Andrew-Cottrell

https://github.com/jquery/jquery/blob/3.6.0/src/core.js#L223

It's not clear to me that the toString.call( obj ) !== "[object Object]" check is needed. The rest of the implementation appears to implement the documented behavior. This check appears to be an optimisation that inadvertently changes the behavior.

Andrew-Cottrell avatar Mar 08 '21 15:03 Andrew-Cottrell

@gibson042 do you know why do we need this part? Tests pass in Chrome & Firefox if you cut it out.

mgol avatar Mar 08 '21 16:03 mgol

Looking at https://github.com/jquery/jquery/commit/e0d3bfa77073a245ca112736a1ed3db07d5adcf6#diff-8ab41fe13597e1554b5d6b4c227b5f123ff2d6726a7f3688a8b8d1224fe1d4f3R231 , there might be/have been supported environments where a window object and/or (IE?) host object had no prototype. Assuming that's not the case now, I have no problem with removing the toString.call( obj ) short-circuit—but note that it will still be possible to trick jQuery.isPlainObject. The function isn't intended to be robust, it's just used in a few places to differentiate "bag of data" input from richer objects like DOM nodes, so it shouldn't actually matter whether an otherwise plain object with a custom ToStringTag is treated as the former or the latter.

gibson042 avatar Mar 08 '21 19:03 gibson042

I've just checked; the toString.call( obj ) check is still needed for IE 11.

mgol avatar Mar 11 '21 13:03 mgol

@Andrew-Cottrell would you like to submit a PR updating the documentation? I think we won't be able to change the implementation.

mgol avatar Mar 15 '21 23:03 mgol

Sorry, I have no prior experience with GitHub PRs and I am currently too busy with work to take the time to learn.

I suggest a single sentence is appended to the Note section, just before the Example section.

Objects with a [Symbol.toStringTag] own property unequal to "Object" are not considered to be plain.

The sentence could be expanded

Objects with a [Symbol.toStringTag] own property unequal to "Object" are not considered to be plain and are unsupported by jQuery.

Or perhaps

jQuery does not support non-prototype objects with a [Symbol.toStringTag] own property.

The same, or a similar, sentence might also be added to https://github.com/jquery/jquery/wiki/Won't-Fix

Andrew-Cottrell avatar Mar 16 '21 09:03 Andrew-Cottrell