isNative issues
zloirock opened this issue · 7 comments
lodash
usesObject#toString
as template forisNative
assuming that is native function. But ES6 changedObject#toString
logic for supportSymbol.toStringTag
.core-js
from first versions adds polyfill for this logic and replacesObject#toString
._.isNative
works wrong for all native functions withcore-js
/babel
and some other libraries:
require('core-js');
require('lodash').isNative(Object); // => false
require('lodash').isNative(Function); // => false
require('lodash').isNative(isNaN); // => false
I will add fallback for lodash
in next version core-js
, but lodash
should use native function whose logic shouldn't be changed in ES6+.
2. lodash
uses isNative
for detect Set
, WeakMap
, some object methods - but why? In most polyfills, native methods wrapped for correct work by latest spec and, with this check, will not work with lodash
. Related #981. Better use correct feature detection.
Yap, I picked Object.prototype.toString
because it's used heavily in other libs and not likely to be mucked with as it's on the Object.prototype
. I didn't think about those mucking with it using defineProperty
. Any recommendations on a method you wouldn't likely touch?
I didn't think about those mucking with it using
defineProperty
.
Wrapping Object.prototype.toString
not requires native defineProperty
- it's already non-enumerable.
Object.prototype.toString = 42;
for(var key in {})console.log('key: ' + key); // nothing
Any recommendations on a method you wouldn't likely touch?
Should be in ES3, not constructor, not Object.prototype
method - someone wrapped them for store non-enum properties or something else, not Array.prototype
method - most of them replaced in es6-shim
, not Math
method - also for better accuracy. Should be as simple as possible. Possible, global isNaN
or isFinite
, their ES6 versions - static Number
methods, but not sure.
There's bugs in at least some engines where overwriting a built-in does make it enumerable. So there's that.
Are you working with @ljharb on your shims?
There's bugs in at least some engines where overwriting a built-in does make it enumerable.
Yep, but in old irrelevant engines :)
About es6-shim
- it's not adds @@toStringTag
logic and not wrapped Object#toString
, but second issue similar:
require('es6-shim');
require('lodash').isNative(Object.keys); // => false
require('lodash').isNative(Object.getPrototypeOf); // => false
require('lodash').isNative(Object.preventExtensions); // => false
I like using an Object.prototype
method as reference because Object.prototype
is seen as off-limits to many devs. I'll kick around using constructor
, propertyIsEnumerable
, or toLocaleString
.
They gotta make sure when they wrap they look like the built-in :)
Instead of Object#toString
- it's impossible - current isNative
uses Function#toString.call(method)
. Using .bind
for fake native source will break #name
property.
I'll kick around using
constructor
ortoLocaleString
.
I remember one library that wrapped Object#toLocaleString
(non-enumerable method in Object.prototype
for old IE). constructor
will be replaced if someone wrap Object
constructor. About propertyIsEnumerable
- possible, I will wrap it for Symbol
polyfill (all shimmed symbols are non enumerable). I think, possible use hasOwnProperty
- for replace it you'd be crazy :)
Ah ya good old hasOwnProperty
. I'll make that change then. I'm fine with isNative
not being 100% bullet proof I just want to put a good effort in.