is-callable
Advanced tools
Comparing version 1.1.3 to 1.1.4
@@ -48,3 +48,3 @@ { | ||
"disallowQuotedKeysInObjects": "allButReserved", | ||
"disallowQuotedKeysInObjects": { "allExcept": ["reserved"] }, | ||
@@ -162,4 +162,17 @@ "disallowSpaceAfterObjectKeys": true, | ||
"disallowSpacesInsideTemplateStringPlaceholders": true | ||
"requireSpaceBeforeObjectValues": true, | ||
"requireSpaceBeforeDestructuredValues": true, | ||
"disallowSpacesInsideTemplateStringPlaceholders": true, | ||
"disallowArrayDestructuringReturn": false, | ||
"requireNewlineBeforeSingleStatementsInIf": false, | ||
"disallowUnusedVariables": true, | ||
"requireSpacesInsideImportedObjectBraces": true, | ||
"requireUseStrict": true | ||
} | ||
@@ -0,1 +1,7 @@ | ||
1.1.4 / 2018-07-02 | ||
================= | ||
* [Fix] improve `class` and arrow function detection (#30, #31) | ||
* [Tests] on all latest node minors; improve matrix | ||
* [Dev Deps] update all dev deps | ||
1.1.3 / 2016-02-27 | ||
@@ -2,0 +8,0 @@ ================= |
12
index.js
@@ -5,10 +5,7 @@ 'use strict'; | ||
var constructorRegex = /^\s*class /; | ||
var isES6ClassFn = function isES6ClassFn(value) { | ||
var constructorRegex = /^\s*class\b/; | ||
var isES6ClassFn = function isES6ClassFunction(value) { | ||
try { | ||
var fnStr = fnToStr.call(value); | ||
var singleStripped = fnStr.replace(/\/\/.*\n/g, ''); | ||
var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, ''); | ||
var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' '); | ||
return constructorRegex.test(spaceStripped); | ||
return constructorRegex.test(fnStr); | ||
} catch (e) { | ||
@@ -19,3 +16,3 @@ return false; // not a function | ||
var tryFunctionObject = function tryFunctionObject(value) { | ||
var tryFunctionObject = function tryFunctionToStr(value) { | ||
try { | ||
@@ -37,2 +34,3 @@ if (isES6ClassFn(value)) { return false; } | ||
if (typeof value !== 'function' && typeof value !== 'object') { return false; } | ||
if (typeof value === 'function' && !value.prototype) { return true; } | ||
if (hasToStringTag) { return tryFunctionObject(value); } | ||
@@ -39,0 +37,0 @@ if (isES6ClassFn(value)) { return false; } |
{ | ||
"name": "is-callable", | ||
"version": "1.1.3", | ||
"version": "1.1.4", | ||
"author": { | ||
@@ -20,12 +20,20 @@ "name": "Jordan Harband", | ||
"scripts": { | ||
"test": "npm run lint && npm run tests-only && npm run security", | ||
"tests-only": "parallelshell 'npm run test:stock' 'npm run test:staging'", | ||
"pretest": "npm run --silent lint", | ||
"test": "npm run --silent tests-only", | ||
"posttest": "npm run --silent security", | ||
"tests-only": "npm run --silent test:stock && npm run --silent test:staging", | ||
"test:stock": "node test.js", | ||
"test:staging": "node --es-staging test.js", | ||
"coverage": "covert test.js", | ||
"coverage-quiet": "covert test.js --quiet", | ||
"coverage": "npm run --silent istanbul", | ||
"covert": "covert test.js", | ||
"covert:quiet": "covert test.js --quiet", | ||
"istanbul": "npm run --silent istanbul:clean && npm run --silent istanbul:std && npm run --silent istanbul:harmony && npm run --silent istanbul:merge && istanbul check", | ||
"istanbul:clean": "rimraf coverage coverage-std coverage-harmony", | ||
"istanbul:merge": "istanbul-merge --out coverage/coverage.raw.json coverage-harmony/coverage.raw.json coverage-std/coverage.raw.json && istanbul report html", | ||
"istanbul:harmony": "node --harmony ./node_modules/istanbul/lib/cli.js cover test.js --dir coverage-harmony", | ||
"istanbul:std": "istanbul cover test.js --report html --dir coverage-std", | ||
"prelint": "editorconfig-tools check *", | ||
"lint": "npm run jscs && npm run eslint", | ||
"jscs": "jscs *.js", | ||
"eslint": "eslint *.js", | ||
"eccheck": "editorconfig-tools check *.js **/*.js > /dev/null", | ||
"security": "nsp check" | ||
@@ -51,14 +59,16 @@ }, | ||
"devDependencies": { | ||
"tape": "^4.4.0", | ||
"@ljharb/eslint-config": "^12.2.1", | ||
"covert": "^1.1.0", | ||
"jscs": "^2.10.1", | ||
"editorconfig-tools": "^0.1.1", | ||
"nsp": "^2.2.0", | ||
"eslint": "^2.2.0", | ||
"@ljharb/eslint-config": "^2.1.1", | ||
"eslint": "^4.19.1", | ||
"foreach": "^2.0.5", | ||
"istanbul": "1.1.0-alpha.1", | ||
"istanbul-merge": "^1.1.1", | ||
"jscs": "^3.0.7", | ||
"make-arrow-function": "^1.1.0", | ||
"make-generator-function": "^1.1.0", | ||
"semver": "^5.1.0", | ||
"foreach": "^2.0.5", | ||
"parallelshell": "^2.0.0" | ||
"nsp": "^3.2.1", | ||
"rimraf": "^2.6.2", | ||
"semver": "^5.5.0", | ||
"tape": "^4.9.1" | ||
}, | ||
@@ -87,2 +97,1 @@ "testling": { | ||
} | ||
65
test.js
@@ -7,9 +7,29 @@ 'use strict'; | ||
var isCallable = require('./'); | ||
var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol'; | ||
var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol'; | ||
var genFn = require('make-generator-function'); | ||
var arrowFn = require('make-arrow-function')(); | ||
var weirdlyCommentedArrowFn; | ||
var asyncFn; | ||
var asyncArrowFn; | ||
try { | ||
/* eslint no-new-func: 0 */ | ||
weirdlyCommentedArrowFn = Function('return cl/*/**/=>/**/ass - 1;')(); | ||
asyncFn = Function('return async function foo() {};')(); | ||
asyncArrowFn = Function('return async () => {};')(); | ||
} catch (e) { /**/ } | ||
var forEach = require('foreach'); | ||
var invokeFunction = function invokeFunction(str) { | ||
var result; | ||
var noop = function () {}; | ||
var classFake = function classFake() { }; // eslint-disable-line func-name-matching | ||
var returnClass = function () { return ' class '; }; | ||
var return3 = function () { return 3; }; | ||
/* for coverage */ | ||
noop(); | ||
classFake(); | ||
returnClass(); | ||
return3(); | ||
/* end for coverage */ | ||
var invokeFunction = function invokeFunctionString(str) { | ||
var result; | ||
try { | ||
@@ -20,3 +40,3 @@ /* eslint-disable no-new-func */ | ||
result = fn(); | ||
} catch (e) { /**/ } | ||
} catch (e) {} | ||
return result; | ||
@@ -27,3 +47,6 @@ }; | ||
var commentedClass = invokeFunction('"use strict"; return class/*kkk*/\n\/\/blah\n Bar\n\/\/blah\n {}'); | ||
var commentedClass = invokeFunction('"use strict"; return class/*kkk*/\n//blah\n Bar\n//blah\n {}'); | ||
var commentedClassOneLine = invokeFunction('"use strict"; return class/**/A{}'); | ||
var classAnonymous = invokeFunction('"use strict"; return class{}'); | ||
var classAnonymousCommentedOneLine = invokeFunction('"use strict"; return class/*/*/{}'); | ||
@@ -61,3 +84,3 @@ test('not callables', function (t) { | ||
var Foo = function Bar() {}; | ||
Foo.prototype = function () {}; | ||
Foo.prototype = noop; | ||
st.equal(true, isCallable(Foo), 'sanity check: Foo is callable'); | ||
@@ -72,8 +95,9 @@ st.equal(false, isCallable(new Foo()), 'instance of Foo is not callable'); | ||
test('@@toStringTag', { skip: !hasSymbols || !Symbol.toStringTag }, function (t) { | ||
var fn = function () { return 3; }; | ||
var fakeFunction = { | ||
toString: function () { return String(fn); }, | ||
valueOf: function () { return fn; } | ||
toString: function () { return String(return3); }, | ||
valueOf: return3 | ||
}; | ||
fakeFunction[Symbol.toStringTag] = 'Function'; | ||
t.equal(String(fakeFunction), String(return3)); | ||
t.equal(Number(fakeFunction), return3()); | ||
t.notOk(isCallable(fakeFunction), 'fake Function with @@toStringTag "Function" is not callable'); | ||
@@ -96,5 +120,5 @@ t.end(); | ||
test('Functions', function (t) { | ||
t.ok(isCallable(function () {}), 'function is callable'); | ||
t.ok(isCallable(function classFake() { }), 'function with name containing "class" is callable'); | ||
t.ok(isCallable(function () { return ' class '; }), 'function with string " class " is callable'); | ||
t.ok(isCallable(noop), 'function is callable'); | ||
t.ok(isCallable(classFake), 'function with name containing "class" is callable'); | ||
t.ok(isCallable(returnClass), 'function with string " class " is callable'); | ||
t.ok(isCallable(isCallable), 'isCallable is callable'); | ||
@@ -106,3 +130,6 @@ t.end(); | ||
forEach(typedArrayNames, function (typedArray) { | ||
if (typeof global[typedArray] !== 'undefined') { | ||
/* istanbul ignore if : covered in node 0.6 */ | ||
if (typeof global[typedArray] === 'undefined') { | ||
st.comment('# SKIP typed array "' + typedArray + '" not supported'); | ||
} else { | ||
st.ok(isCallable(global[typedArray]), typedArray + ' is callable'); | ||
@@ -121,9 +148,19 @@ } | ||
t.ok(isCallable(arrowFn), 'arrow function is callable'); | ||
t.ok(isCallable(weirdlyCommentedArrowFn), 'weirdly commented arrow functions are callable'); | ||
t.end(); | ||
}); | ||
test('"Class" constructors', { skip: !classConstructor || !commentedClass }, function (t) { | ||
test('"Class" constructors', { skip: !classConstructor || !commentedClass || !commentedClassOneLine || !classAnonymous }, function (t) { | ||
t.notOk(isCallable(classConstructor), 'class constructors are not callable'); | ||
t.notOk(isCallable(commentedClass), 'class constructors with comments in the signature are not callable'); | ||
t.notOk(isCallable(commentedClassOneLine), 'one-line class constructors with comments in the signature are not callable'); | ||
t.notOk(isCallable(classAnonymous), 'anonymous class constructors are not callable'); | ||
t.notOk(isCallable(classAnonymousCommentedOneLine), 'anonymous one-line class constructors with comments in the signature are not callable'); | ||
t.end(); | ||
}); | ||
test('`async function`s', { skip: !asyncFn }, function (t) { | ||
t.ok(isCallable(asyncFn), '`async function`s are callable'); | ||
t.ok(isCallable(asyncArrowFn), '`async` arrow functions are callable'); | ||
t.end(); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses eval() which is a dangerous function. This prevents the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
30555
12
285
14
4