You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The parse method produces objects with a strange prototype. Rather than leaving it at Object.prototype (the default) or using null (mostly better), the objects get an indirect prototype, an object that itself has a null prototype, and is also sealed. I cannot imagine any valid reason for this: it’s purely inefficiency. But it also thwarts detection of a null prototype, which is a bad thing, because “is its prototype Object.prototype or null” is a customary “simple object” check. For a concrete example of what this breaks, trying to use require("@ltd/j-toml").parse in Eleventy data or front matter ends up ignoring everything if deep data merging is enabled (which it is by default), because it does this kind of “simple object” check, or uses the iteration prototcol if it isn’t simple—and this gets erroneously detected as not simple.
And replacing all occurrences of NULL with null. Simpler, faster, more efficient, less troublesome. There may be more related stuff to it, but I’ve decided not to use this library because of this and other troublesome prototype shenanigans (e.g. how Datetime effectively deletes methods, which is a bad thing to do and almost always worse than just not doing that—yeah, if you try accessing the “wrong” methods on LocalDate you’ll effectively get a T00:00:00Z, but that’s not so bad), so I haven’t delved particularly deeply.
Sample Node transcript showing the problem and a hacky postprocessing fix for the prototype (though you’d need to do this recursively):
Sorry for replying late, I have read you issue days before.
What's counter-intuitive, object without any proto is slower than object with a proto for tenfold. I can't give you ready-made https://jsperf.com link because the site is down... You can try below in https://jsbench.me/:
// setupwindow.plain={};window.null=Object.create(null);window.Null=Object.create(Object.create(null));// test case 1: x10'use strict';constobject=window.plain;for(leti=1e6;--i;){object.key??=null;}// test case 2: x1'use strict';constobject=window.null;for(leti=1e6;--i;){object.key??=null;}// test case 3: x10'use strict';constobject=window.Null;for(leti=1e6;--i;){object.key??=null;}
Object.create(null) will make more than tenfold slower, while Object.create(NULL) can regain to {} with proto properties safe.
But what you said is also important, which I didn't meet before. I want to know that, what bad thing will actually happen, when an object is not simple? (What do you mean of "uses the iteration prototcol"?)
I searched a popular lib merge-options and it's dep is-plain-obj, it seems thing should work right:
How could you got a T00:00:00Z? I can't reproduce it or find any trace of it by the source code. Would you please give a use case to help to figure out that? If it exists, it's definitely not expected behaviour.
The
parse
method produces objects with a strange prototype. Rather than leaving it atObject.prototype
(the default) or usingnull
(mostly better), the objects get an indirect prototype, an object that itself has a null prototype, and is also sealed. I cannot imagine any valid reason for this: it’s purely inefficiency. But it also thwarts detection of a null prototype, which is a bad thing, because “is its prototypeObject.prototype
ornull
” is a customary “simple object” check. For a concrete example of what this breaks, trying to userequire("@ltd/j-toml").parse
in Eleventy data or front matter ends up ignoring everything if deep data merging is enabled (which it is by default), because it does this kind of “simple object” check, or uses the iteration prototcol if it isn’t simple—and this gets erroneously detected as not simple.I propose removing this:
And replacing all occurrences of
NULL
withnull
. Simpler, faster, more efficient, less troublesome. There may be more related stuff to it, but I’ve decided not to use this library because of this and other troublesome prototype shenanigans (e.g. howDatetime
effectively deletes methods, which is a bad thing to do and almost always worse than just not doing that—yeah, if you try accessing the “wrong” methods onLocalDate
you’ll effectively get a T00:00:00Z, but that’s not so bad), so I haven’t delved particularly deeply.Sample Node transcript showing the problem and a hacky postprocessing fix for the prototype (though you’d need to do this recursively):
The text was updated successfully, but these errors were encountered: