1
|
'use strict';
|
2
|
|
3
|
/* eslint no-magic-numbers: 1 */
|
4
|
|
5
|
var test = require('tape');
|
6
|
var isCallable = require('../');
|
7
|
var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
|
8
|
var genFn = require('make-generator-function');
|
9
|
var arrowFn = require('make-arrow-function')();
|
10
|
var weirdlyCommentedArrowFn;
|
11
|
var asyncFn;
|
12
|
var asyncArrowFn;
|
13
|
try {
|
14
|
/* eslint-disable no-new-func */
|
15
|
weirdlyCommentedArrowFn = Function('return cl/*/**/=>/**/ass - 1;')();
|
16
|
asyncFn = Function('return async function foo() {};')();
|
17
|
asyncArrowFn = Function('return async () => {};')();
|
18
|
/* eslint-enable no-new-func */
|
19
|
} catch (e) { /**/ }
|
20
|
var forEach = require('foreach');
|
21
|
|
22
|
var noop = function () {};
|
23
|
var classFake = function classFake() { }; // eslint-disable-line func-name-matching
|
24
|
var returnClass = function () { return ' class '; };
|
25
|
var return3 = function () { return 3; };
|
26
|
/* for coverage */
|
27
|
noop();
|
28
|
classFake();
|
29
|
returnClass();
|
30
|
return3();
|
31
|
/* end for coverage */
|
32
|
|
33
|
var invokeFunction = function invokeFunctionString(str) {
|
34
|
var result;
|
35
|
try {
|
36
|
/* eslint-disable no-new-func */
|
37
|
var fn = Function(str);
|
38
|
/* eslint-enable no-new-func */
|
39
|
result = fn();
|
40
|
} catch (e) {}
|
41
|
return result;
|
42
|
};
|
43
|
|
44
|
var classConstructor = invokeFunction('"use strict"; return class Foo {}');
|
45
|
|
46
|
var commentedClass = invokeFunction('"use strict"; return class/*kkk*/\n//blah\n Bar\n//blah\n {}');
|
47
|
var commentedClassOneLine = invokeFunction('"use strict"; return class/**/A{}');
|
48
|
var classAnonymous = invokeFunction('"use strict"; return class{}');
|
49
|
var classAnonymousCommentedOneLine = invokeFunction('"use strict"; return class/*/*/{}');
|
50
|
|
51
|
test('not callables', function (t) {
|
52
|
t.test('non-number/string primitives', function (st) {
|
53
|
st.notOk(isCallable(), 'undefined is not callable');
|
54
|
st.notOk(isCallable(null), 'null is not callable');
|
55
|
st.notOk(isCallable(false), 'false is not callable');
|
56
|
st.notOk(isCallable(true), 'true is not callable');
|
57
|
st.end();
|
58
|
});
|
59
|
|
60
|
t.notOk(isCallable([]), 'array is not callable');
|
61
|
t.notOk(isCallable({}), 'object is not callable');
|
62
|
t.notOk(isCallable(/a/g), 'regex literal is not callable');
|
63
|
t.notOk(isCallable(new RegExp('a', 'g')), 'regex object is not callable');
|
64
|
t.notOk(isCallable(new Date()), 'new Date() is not callable');
|
65
|
|
66
|
t.test('numbers', function (st) {
|
67
|
st.notOk(isCallable(42), 'number is not callable');
|
68
|
st.notOk(isCallable(Object(42)), 'number object is not callable');
|
69
|
st.notOk(isCallable(NaN), 'NaN is not callable');
|
70
|
st.notOk(isCallable(Infinity), 'Infinity is not callable');
|
71
|
st.end();
|
72
|
});
|
73
|
|
74
|
t.test('strings', function (st) {
|
75
|
st.notOk(isCallable('foo'), 'string primitive is not callable');
|
76
|
st.notOk(isCallable(Object('foo')), 'string object is not callable');
|
77
|
st.end();
|
78
|
});
|
79
|
|
80
|
t.test('non-function with function in its [[Prototype]] chain', function (st) {
|
81
|
var Foo = function Bar() {};
|
82
|
Foo.prototype = noop;
|
83
|
st.equal(true, isCallable(Foo), 'sanity check: Foo is callable');
|
84
|
st.equal(false, isCallable(new Foo()), 'instance of Foo is not callable');
|
85
|
st.end();
|
86
|
});
|
87
|
|
88
|
t.end();
|
89
|
});
|
90
|
|
91
|
test('@@toStringTag', { skip: !hasSymbols || !Symbol.toStringTag }, function (t) {
|
92
|
var fakeFunction = {
|
93
|
toString: function () { return String(return3); },
|
94
|
valueOf: return3
|
95
|
};
|
96
|
fakeFunction[Symbol.toStringTag] = 'Function';
|
97
|
t.equal(String(fakeFunction), String(return3));
|
98
|
t.equal(Number(fakeFunction), return3());
|
99
|
t.notOk(isCallable(fakeFunction), 'fake Function with @@toStringTag "Function" is not callable');
|
100
|
t.end();
|
101
|
});
|
102
|
|
103
|
var typedArrayNames = [
|
104
|
'Int8Array',
|
105
|
'Uint8Array',
|
106
|
'Uint8ClampedArray',
|
107
|
'Int16Array',
|
108
|
'Uint16Array',
|
109
|
'Int32Array',
|
110
|
'Uint32Array',
|
111
|
'Float32Array',
|
112
|
'Float64Array'
|
113
|
];
|
114
|
|
115
|
test('Functions', function (t) {
|
116
|
t.ok(isCallable(noop), 'function is callable');
|
117
|
t.ok(isCallable(classFake), 'function with name containing "class" is callable');
|
118
|
t.ok(isCallable(returnClass), 'function with string " class " is callable');
|
119
|
t.ok(isCallable(isCallable), 'isCallable is callable');
|
120
|
t.end();
|
121
|
});
|
122
|
|
123
|
test('Typed Arrays', function (st) {
|
124
|
forEach(typedArrayNames, function (typedArray) {
|
125
|
/* istanbul ignore if : covered in node 0.6 */
|
126
|
if (typeof global[typedArray] === 'undefined') {
|
127
|
st.comment('# SKIP typed array "' + typedArray + '" not supported');
|
128
|
} else {
|
129
|
st.ok(isCallable(global[typedArray]), typedArray + ' is callable');
|
130
|
}
|
131
|
});
|
132
|
st.end();
|
133
|
});
|
134
|
|
135
|
test('Generators', { skip: !genFn }, function (t) {
|
136
|
t.ok(isCallable(genFn), 'generator function is callable');
|
137
|
t.end();
|
138
|
});
|
139
|
|
140
|
test('Arrow functions', { skip: !arrowFn }, function (t) {
|
141
|
t.ok(isCallable(arrowFn), 'arrow function is callable');
|
142
|
t.ok(isCallable(weirdlyCommentedArrowFn), 'weirdly commented arrow functions are callable');
|
143
|
t.end();
|
144
|
});
|
145
|
|
146
|
test('"Class" constructors', { skip: !classConstructor || !commentedClass || !commentedClassOneLine || !classAnonymous }, function (t) {
|
147
|
t.notOk(isCallable(classConstructor), 'class constructors are not callable');
|
148
|
t.notOk(isCallable(commentedClass), 'class constructors with comments in the signature are not callable');
|
149
|
t.notOk(isCallable(commentedClassOneLine), 'one-line class constructors with comments in the signature are not callable');
|
150
|
t.notOk(isCallable(classAnonymous), 'anonymous class constructors are not callable');
|
151
|
t.notOk(isCallable(classAnonymousCommentedOneLine), 'anonymous one-line class constructors with comments in the signature are not callable');
|
152
|
t.end();
|
153
|
});
|
154
|
|
155
|
test('`async function`s', { skip: !asyncFn }, function (t) {
|
156
|
t.ok(isCallable(asyncFn), '`async function`s are callable');
|
157
|
t.ok(isCallable(asyncArrowFn), '`async` arrow functions are callable');
|
158
|
t.end();
|
159
|
});
|