api.jquery.com
api.jquery.com copied to clipboard
jQuery.isPlainObject( { ... } ) can be tricked by manipulating Symbol.toStringTag
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".
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.
@gibson042 do you know why do we need this part? Tests pass in Chrome & Firefox if you cut it out.
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.
I've just checked; the toString.call( obj ) check is still needed for IE 11.
@Andrew-Cottrell would you like to submit a PR updating the documentation? I think we won't be able to change the implementation.
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