is-callable
Advanced tools
Comparing version 1.2.5 to 1.2.6
@@ -8,2 +8,14 @@ # Changelog | ||
## [v1.2.6](https://github.com/inspect-js/is-callable/compare/v1.2.5...v1.2.6) - 2022-09-14 | ||
### Commits | ||
- [Fix] work for `document.all` in Firefox 3 and IE 6-8 [`015132a`](https://github.com/inspect-js/is-callable/commit/015132aaef886ec777b5b3593ef4ce461dd0c7d4) | ||
- [Test] skip function toString check for nullish values [`8698116`](https://github.com/inspect-js/is-callable/commit/8698116f95eb59df8b48ec8e4585fc1cdd8cae9f) | ||
- [readme] add "supported engines" section [`0442207`](https://github.com/inspect-js/is-callable/commit/0442207a89a1554d41ba36daf21862ef7ccbd500) | ||
- [Tests] skip one of the fixture objects in FF 3.6 [`a501141`](https://github.com/inspect-js/is-callable/commit/a5011410bc6edb276c6ec8b47ce5c5d83c4bee15) | ||
- [Tests] allow `class` constructor tests to fail in FF v45 - v54, which has undetectable classes [`b12e4a4`](https://github.com/inspect-js/is-callable/commit/b12e4a4d8c438678bd7710f9f896680150766b51) | ||
- [Fix] Safari 4: regexes should not be considered callable [`4b732ff`](https://github.com/inspect-js/is-callable/commit/4b732ffa34346db3f0193ea4e46b7d4e637e6c82) | ||
- [Fix] properly recognize `document.all` in Safari 4 [`3193735`](https://github.com/inspect-js/is-callable/commit/319373525dc4603346661641840cd9a3e0613136) | ||
## [v1.2.5](https://github.com/inspect-js/is-callable/compare/v1.2.4...v1.2.5) - 2022-09-11 | ||
@@ -10,0 +22,0 @@ |
33
index.js
@@ -46,15 +46,29 @@ 'use strict'; | ||
var toStr = Object.prototype.toString; | ||
var objectClass = '[object Object]'; | ||
var fnClass = '[object Function]'; | ||
var genClass = '[object GeneratorFunction]'; | ||
var ddaClass = '[object HTMLAllCollection]'; | ||
var hasToStringTag = typeof Symbol === 'function' && !!Symbol.toStringTag; // better: use `has-tostringtag` | ||
var isDDA = typeof document === 'object' ? function isDocumentDotAll(value) { | ||
/* globals document: false */ | ||
// in IE 8, typeof document.all is "object" | ||
if (typeof value === 'undefined' || typeof value === 'object') { | ||
try { | ||
return value('') === null; | ||
} catch (e) { /**/ } | ||
var isIE68 = !(0 in [,]); // eslint-disable-line no-sparse-arrays, comma-spacing | ||
var isDDA = function isDocumentDotAll() { return false; }; | ||
if (typeof document === 'object') { | ||
// Firefox 3 canonicalized DDA to undefined when it's not accessed directly | ||
var all = document.all; | ||
if (toStr.call(all) === toStr.call(document.all)) { | ||
isDDA = function isDocumentDotAll(value) { | ||
/* globals document: false */ | ||
// in IE 6-8, typeof document.all is "object" and it's truthy | ||
if ((isIE68 || !value) && (typeof value === 'undefined' || typeof value === 'object')) { | ||
try { | ||
var str = toStr.call(value); | ||
// IE 6-8 uses `objectClass` | ||
return (str === ddaClass || str === objectClass) && value('') == null; // eslint-disable-line eqeqeq | ||
} catch (e) { /**/ } | ||
} | ||
return false; | ||
}; | ||
} | ||
return false; | ||
} : function () { return false; }; | ||
} | ||
@@ -78,3 +92,2 @@ module.exports = reflectApply | ||
if (typeof value !== 'function' && typeof value !== 'object') { return false; } | ||
if (typeof value === 'function' && !value.prototype) { return true; } | ||
if (hasToStringTag) { return tryFunctionObject(value); } | ||
@@ -81,0 +94,0 @@ if (isES6ClassFn(value)) { return false; } |
{ | ||
"name": "is-callable", | ||
"version": "1.2.5", | ||
"version": "1.2.6", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "Jordan Harband", |
@@ -14,2 +14,15 @@ # is-callable <sup>[![Version Badge][2]][1]</sup> | ||
## Supported engines | ||
Automatically tested in every minor version of node. | ||
Manually tested in: | ||
- Safari: v4 - v15 <sub>(4, 5, 5.1, 6.0.5, 6.2, 7.1, 8, 9.1.3, 10.1.2, 11.1.2, 12.1, 13.1.2, 14.1.2, 15.3, 15.6.1)</sub> | ||
- Note: Safari 9 has `class`, but `Function.prototype.toString` hides that progeny and makes them look like functions, so `class` constructors will be reported by this package as callable, when they are not in fact callable. | ||
- Chrome: v15 - v81, v83 - v106<sub>(every integer version)</sub> | ||
- Note: This includes Edge v80+ and Opera v15+, which matches Chrome | ||
- Firefox: v3, v3.6, v4 - v105 <sub>(every integer version)</sub> | ||
- Note: Firefox v45 - v54 has `class`, but `Function.prototype.toString` hides that progeny and makes them look like functions, so `class` constructors will be reported by this package as callable, when they are not in fact callable. | ||
- IE: v6 - v11<sub>(every integer version</sub> | ||
- Opera: v11.1, v11.5, v11.6, 12?, v12.1, v12.12?, v12.14, v12.15, v12.16, v15+ <sub>v15+ matches Chrome</sub> | ||
## Example | ||
@@ -16,0 +29,0 @@ |
@@ -23,2 +23,10 @@ 'use strict'; | ||
var isIE68 = !(0 in [undefined]); | ||
var isFirefox = typeof window !== 'undefined' && ('netscape' in window) && (/ rv:/).test(navigator.userAgent); | ||
var fnToStringCoerces; | ||
try { | ||
Function.prototype.toString.call(v.uncoercibleFnObject); | ||
fnToStringCoerces = true; | ||
} catch (e) { | ||
fnToStringCoerces = false; | ||
} | ||
@@ -64,2 +72,3 @@ var noop = function () {}; | ||
var classConstructor = invokeFunction('"use strict"; return class Foo {}'); | ||
var hasDetectableClasses = classConstructor && Function.prototype.toString.call(classConstructor) === 'class Foo {}'; | ||
@@ -83,2 +92,21 @@ var commentedClass = invokeFunction('"use strict"; return class/*kkk*/\n//blah\n Bar\n//blah\n {}'); | ||
]), function (nonFunction) { | ||
if (fnToStringCoerces && nonFunction === v.coercibleFnObject) { | ||
t.comment('FF 3.6 has a Function toString that coerces its receiver, so this test is skipped'); | ||
return; | ||
} | ||
if (nonFunction != null) { // eslint-disable-line eqeqeq | ||
if (isFirefox) { | ||
// Firefox 3 throws some kind of *object* here instead of a proper error | ||
t['throws']( | ||
function () { Function.prototype.toString.call(nonFunction); }, | ||
inspect(nonFunction) + ' can not be used with Function toString' | ||
); | ||
} else { | ||
t['throws']( | ||
function () { Function.prototype.toString.call(nonFunction); }, | ||
TypeError, | ||
inspect(nonFunction) + ' can not be used with Function toString' | ||
); | ||
} | ||
} | ||
t.equal(isCallable(nonFunction), false, inspect(nonFunction) + ' is not callable'); | ||
@@ -140,3 +168,8 @@ }); | ||
test('"Class" constructors', { skip: !classConstructor || !commentedClass || !commentedClassOneLine || !classAnonymous }, function (t) { | ||
test('"Class" constructors', { | ||
skip: !classConstructor || !commentedClass || !commentedClassOneLine || !classAnonymous, todo: !hasDetectableClasses | ||
}, function (t) { | ||
if (!hasDetectableClasses) { | ||
t.comment('WARNING: This engine does not support detectable classes'); | ||
} | ||
t.notOk(isCallable(classConstructor), 'class constructors are not callable'); | ||
@@ -174,4 +207,7 @@ t.notOk(isCallable(commentedClass), 'class constructors with comments in the signature are not callable'); | ||
st.notOk(isCallable(document), 'document is not callable'); | ||
st.ok(isCallable(document.all), 'document.all is callable'); | ||
var all = document.all; | ||
var isFF3 = Object.prototype.toString(all) === Object.prototype.toString.call(document.all); | ||
st.equal(isCallable(document.all), isFF3, 'document.all is ' + (isFF3 ? 'not ' : '') + 'callable'); | ||
st.end(); | ||
@@ -187,5 +223,5 @@ }); | ||
t.test(name, { skip: !constructor }, function (st) { | ||
st.match(typeof constructor, /^(?:function|object)$/, name + ' is a function'); | ||
st.match(typeof constructor, /^(?:function|object)$/, name + ' is a function or object'); | ||
st.equal(isCallable(constructor), !isIE68, name + ' is ' + (isIE68 ? 'not ' : '') + 'callable'); | ||
st.equal(isCallable(constructor), typeof constructor === 'function', name + ' is ' + (isIE68 ? 'not ' : '') + 'callable'); | ||
@@ -192,0 +228,0 @@ st.end(); |
Sorry, the diff of this file is not supported yet
26768
285
81