Skip to content

Commit 8197574

Browse files
axetroysindresorhusfisker
authoredJan 21, 2025··
Add no-instanceof-builtin-object rule (#2523)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com> Co-authored-by: fisker <lionkay@gmail.com>
1 parent 3b5faba commit 8197574

14 files changed

+2596
-17
lines changed
 
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Disallow `instanceof` with built-in objects
2+
3+
💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs).
4+
5+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
6+
7+
<!-- end auto-generated rule header -->
8+
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->
9+
10+
Using `instanceof` to determine the type of an object has [limitations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms).
11+
12+
Therefore, it is recommended to use a safer method, like `Object.prototype.toString.call(foo)` or the npm package [@sindresorhus/is](https://www.npmjs.com/package/@sindresorhus/is) to determine the type of an object.
13+
14+
## Examples
15+
16+
```js
17+
foo instanceof String; //
18+
typeof foo === 'string'; //
19+
```
20+
21+
```js
22+
foo instanceof Number; //
23+
typeof foo === 'number'; //
24+
```
25+
26+
```js
27+
foo instanceof Boolean; //
28+
typeof foo === 'boolean'; //
29+
```
30+
31+
```js
32+
foo instanceof BigInt; //
33+
typeof foo === 'bigint'; //
34+
```
35+
36+
```js
37+
foo instanceof Symbol; //
38+
typeof foo === 'symbol'; //
39+
```
40+
41+
```js
42+
foo instanceof Array; //
43+
Array.isArray(foo); //
44+
```
45+
46+
```js
47+
foo instanceof Function; //
48+
typeof foo === 'function'; //
49+
```
50+
51+
```js
52+
foo instanceof Object; //
53+
Object.prototype.toString.call(foo) === '[object Object]'; //
54+
```
55+
56+
```js
57+
import is from '@sindresorhus/is';
58+
59+
foo instanceof Map; //
60+
is(foo) === 'Map'; //
61+
```
62+
63+
## Options
64+
65+
### strategy
66+
67+
Type: `'loose' | 'strict'`\
68+
Default: `'loose'`
69+
70+
The matching strategy:
71+
72+
- `'loose'` - Matches the primitive type (`string`, `number`, `boolean`, `bigint`, `symbol`) constructors, `Function`, and `Array`.
73+
- `'strict'` - Matches all built-in constructors.
74+
75+
```js
76+
"unicorn/no-instanceof-builtin-object": [
77+
"error",
78+
{
79+
"strategy": "strict"
80+
}
81+
]
82+
```
83+
84+
### include
85+
86+
Type: `string[]`\
87+
Default: `[]`
88+
89+
Specify the constructors that should be validated.
90+
91+
```js
92+
"unicorn/no-instanceof-builtin-object": [
93+
"error",
94+
{
95+
"include": [
96+
"WebWorker",
97+
"HTMLElement"
98+
]
99+
}
100+
]
101+
```
102+
103+
### exclude
104+
105+
Type: `string[]`\
106+
Default: `[]`
107+
108+
Specifies the constructors that should be excluded, with this rule taking precedence over others.
109+
110+
```js
111+
"unicorn/no-instanceof-builtin-object": [
112+
"error",
113+
{
114+
"exclude": [
115+
"String",
116+
"Number"
117+
]
118+
}
119+
]
120+
```
121+
122+
### useErrorIsError
123+
124+
Type: `boolean`\
125+
Default: `false`
126+
127+
Specifies using [`Error.isError()`](https://github.com/tc39/proposal-is-error) to determine whether it is an error object.
128+
129+
```js
130+
"unicorn/no-instanceof-builtin-object": [
131+
"error",
132+
{
133+
"strategy": "strict",
134+
"useErrorIsError": true
135+
}
136+
]
137+
```
138+
139+
This option will be removed at some point in the future.

‎readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export default [
8686
| [no-for-loop](docs/rules/no-for-loop.md) | Do not use a `for` loop that can be replaced with a `for-of` loop. || 🔧 | 💡 |
8787
| [no-hex-escape](docs/rules/no-hex-escape.md) | Enforce the use of Unicode escapes instead of hexadecimal escapes. || 🔧 | |
8888
| [no-instanceof-array](docs/rules/no-instanceof-array.md) | Require `Array.isArray()` instead of `instanceof Array`. || 🔧 | |
89+
| [no-instanceof-builtin-object](docs/rules/no-instanceof-builtin-object.md) | Disallow `instanceof` with built-in objects || 🔧 | |
8990
| [no-invalid-fetch-options](docs/rules/no-invalid-fetch-options.md) | Disallow invalid options in `fetch()` and `new Request()`. || | |
9091
| [no-invalid-remove-event-listener](docs/rules/no-invalid-remove-event-listener.md) | Prevent calling `EventTarget#removeEventListener()` with the result of an expression. || | |
9192
| [no-keyword-prefix](docs/rules/no-keyword-prefix.md) | Disallow identifiers starting with `new` or `class`. | | | |

‎rules/catch-error-name.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {isRegExp} from 'node:util/types';
12
import {findVariable} from '@eslint-community/eslint-utils';
23
import avoidCapture from './utils/avoid-capture.js';
34
import {renameVariable} from './fix/index.js';
@@ -40,7 +41,7 @@ const create = context => {
4041
};
4142
const {name: expectedName} = options;
4243
const ignore = options.ignore.map(
43-
pattern => pattern instanceof RegExp ? pattern : new RegExp(pattern, 'u'),
44+
pattern => isRegExp(pattern) ? pattern : new RegExp(pattern, 'u'),
4445
);
4546
const isNameAllowed = name =>
4647
name === expectedName

‎rules/error-message.js

+1-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {getStaticValue} from '@eslint-community/eslint-utils';
22
import isShadowed from './utils/is-shadowed.js';
33
import {isCallOrNewExpression} from './ast/index.js';
4+
import builtinErrors from './shared/builtin-errors.js';
45

56
const MESSAGE_ID_MISSING_MESSAGE = 'missing-message';
67
const MESSAGE_ID_EMPTY_MESSAGE = 'message-is-empty-string';
@@ -11,19 +12,6 @@ const messages = {
1112
[MESSAGE_ID_NOT_STRING]: 'Error message should be a string.',
1213
};
1314

14-
const builtinErrors = [
15-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
16-
'Error',
17-
'EvalError',
18-
'RangeError',
19-
'ReferenceError',
20-
'SyntaxError',
21-
'TypeError',
22-
'URIError',
23-
'InternalError',
24-
'AggregateError',
25-
];
26-
2715
/** @param {import('eslint').Rule.RuleContext} context */
2816
const create = context => {
2917
context.on(['CallExpression', 'NewExpression'], expression => {

‎rules/expiring-todo-comments.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path';
2+
import {isRegExp} from 'node:util/types';
23
import {readPackageUpSync} from 'read-package-up';
34
import semver from 'semver';
45
import * as ci from 'ci-info';
@@ -286,7 +287,7 @@ const create = context => {
286287
};
287288

288289
const ignoreRegexes = options.ignore.map(
289-
pattern => pattern instanceof RegExp ? pattern : new RegExp(pattern, 'u'),
290+
pattern => isRegExp(pattern) ? pattern : new RegExp(pattern, 'u'),
290291
);
291292

292293
const dirname = path.dirname(context.filename);

‎rules/filename-case.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path';
2+
import {isRegExp} from 'node:util/types';
23
import {
34
camelCase,
45
kebabCase,
@@ -164,7 +165,7 @@ const create = context => {
164165
const options = context.options[0] || {};
165166
const chosenCases = getChosenCases(options);
166167
const ignore = (options.ignore || []).map(item => {
167-
if (item instanceof RegExp) {
168+
if (isRegExp(item)) {
168169
return item;
169170
}
170171

‎rules/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import noEmptyFile from './no-empty-file.js';
3131
import noForLoop from './no-for-loop.js';
3232
import noHexEscape from './no-hex-escape.js';
3333
import noInstanceofArray from './no-instanceof-array.js';
34+
import noInstanceofBuiltinObject from './no-instanceof-builtin-object.js';
3435
import noInvalidFetchOptions from './no-invalid-fetch-options.js';
3536
import noInvalidRemoveEventListener from './no-invalid-remove-event-listener.js';
3637
import noKeywordPrefix from './no-keyword-prefix.js';
@@ -156,6 +157,7 @@ const rules = {
156157
'no-for-loop': createRule(noForLoop, 'no-for-loop'),
157158
'no-hex-escape': createRule(noHexEscape, 'no-hex-escape'),
158159
'no-instanceof-array': createRule(noInstanceofArray, 'no-instanceof-array'),
160+
'no-instanceof-builtin-object': createRule(noInstanceofBuiltinObject, 'no-instanceof-builtin-object'),
159161
'no-invalid-fetch-options': createRule(noInvalidFetchOptions, 'no-invalid-fetch-options'),
160162
'no-invalid-remove-event-listener': createRule(noInvalidRemoveEventListener, 'no-invalid-remove-event-listener'),
161163
'no-keyword-prefix': createRule(noKeywordPrefix, 'no-keyword-prefix'),

‎rules/no-instanceof-builtin-object.js

+211
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
import {checkVueTemplate} from './utils/rule.js';
2+
import {getParenthesizedRange} from './utils/parentheses.js';
3+
import {replaceNodeOrTokenAndSpacesBefore, fixSpaceAroundKeyword} from './fix/index.js';
4+
import builtinErrors from './shared/builtin-errors.js';
5+
import typedArray from './shared/typed-array.js';
6+
7+
const isInstanceofToken = token => token.value === 'instanceof' && token.type === 'Keyword';
8+
9+
const MESSAGE_ID = 'no-instanceof-builtin-object';
10+
const messages = {
11+
[MESSAGE_ID]: 'Avoid using `instanceof` for type checking as it can lead to unreliable results.',
12+
};
13+
14+
const looseStrategyConstructors = new Set([
15+
'String',
16+
'Number',
17+
'Boolean',
18+
'BigInt',
19+
'Symbol',
20+
'Array',
21+
'Function',
22+
]);
23+
24+
const strictStrategyConstructors = new Set([
25+
// Error types
26+
...builtinErrors,
27+
28+
// Collection types
29+
'Map',
30+
'Set',
31+
'WeakMap',
32+
'WeakRef',
33+
'WeakSet',
34+
35+
// Arrays and Typed Arrays
36+
'ArrayBuffer',
37+
...typedArray,
38+
39+
// Data types
40+
'Object',
41+
42+
// Regular Expressions
43+
'RegExp',
44+
45+
// Async and functions
46+
'Promise',
47+
'Proxy',
48+
49+
// Other
50+
'DataView',
51+
'Date',
52+
'SharedArrayBuffer',
53+
'FinalizationRegistry',
54+
]);
55+
56+
const replaceWithFunctionCall = (node, sourceCode, functionName) => function * (fixer) {
57+
const {tokenStore, instanceofToken} = getInstanceOfToken(sourceCode, node);
58+
const {left, right} = node;
59+
60+
yield * fixSpaceAroundKeyword(fixer, node, sourceCode);
61+
62+
const range = getParenthesizedRange(left, tokenStore);
63+
yield fixer.insertTextBeforeRange(range, functionName + '(');
64+
yield fixer.insertTextAfterRange(range, ')');
65+
66+
yield * replaceNodeOrTokenAndSpacesBefore(instanceofToken, '', fixer, sourceCode, tokenStore);
67+
yield * replaceNodeOrTokenAndSpacesBefore(right, '', fixer, sourceCode, tokenStore);
68+
};
69+
70+
const replaceWithTypeOfExpression = (node, sourceCode) => function * (fixer) {
71+
const {tokenStore, instanceofToken} = getInstanceOfToken(sourceCode, node);
72+
const {left, right} = node;
73+
74+
// Check if the node is in a Vue template expression
75+
const vueExpressionContainer = sourceCode.getAncestors(node).findLast(ancestor => ancestor.type === 'VExpressionContainer');
76+
77+
// Get safe quote
78+
const safeQuote = vueExpressionContainer ? (sourceCode.getText(vueExpressionContainer)[0] === '"' ? '\'' : '"') : '\'';
79+
80+
yield * fixSpaceAroundKeyword(fixer, node, sourceCode);
81+
82+
const leftRange = getParenthesizedRange(left, tokenStore);
83+
yield fixer.insertTextBeforeRange(leftRange, 'typeof ');
84+
85+
yield fixer.replaceText(instanceofToken, '===');
86+
87+
const rightRange = getParenthesizedRange(right, tokenStore);
88+
89+
yield fixer.replaceTextRange(rightRange, safeQuote + sourceCode.getText(right).toLowerCase() + safeQuote);
90+
};
91+
92+
const getInstanceOfToken = (sourceCode, node) => {
93+
const {left} = node;
94+
95+
let tokenStore = sourceCode;
96+
let instanceofToken = tokenStore.getTokenAfter(left, isInstanceofToken);
97+
if (!instanceofToken && sourceCode.parserServices.getTemplateBodyTokenStore) {
98+
tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore();
99+
instanceofToken = tokenStore.getTokenAfter(left, isInstanceofToken);
100+
}
101+
102+
return {tokenStore, instanceofToken};
103+
};
104+
105+
/** @param {import('eslint').Rule.RuleContext} context */
106+
const create = context => {
107+
const {
108+
useErrorIsError = false,
109+
strategy = 'loose',
110+
include = [],
111+
exclude = [],
112+
} = context.options[0] ?? {};
113+
114+
const {sourceCode} = context;
115+
116+
return {
117+
/** @param {import('estree').BinaryExpression} node */
118+
BinaryExpression(node) {
119+
const {right, operator} = node;
120+
121+
if (right.type !== 'Identifier' || operator !== 'instanceof' || exclude.includes(right.name)) {
122+
return;
123+
}
124+
125+
if (!looseStrategyConstructors.has(right.name) && !strictStrategyConstructors.has(right.name) && !include.includes(right.name)) {
126+
return;
127+
}
128+
129+
/** @type {import('eslint').Rule.ReportDescriptor} */
130+
const problem = {
131+
node,
132+
messageId: MESSAGE_ID,
133+
};
134+
135+
if (
136+
right.name === 'Array'
137+
|| (right.name === 'Error' && useErrorIsError)
138+
) {
139+
const functionName = right.name === 'Array' ? 'Array.isArray' : 'Error.isError';
140+
problem.fix = replaceWithFunctionCall(node, sourceCode, functionName);
141+
return problem;
142+
}
143+
144+
// Loose strategy by default
145+
if (looseStrategyConstructors.has(right.name)) {
146+
problem.fix = replaceWithTypeOfExpression(node, sourceCode);
147+
return problem;
148+
}
149+
150+
// Strict strategy
151+
if (strategy !== 'strict' && include.length === 0) {
152+
return;
153+
}
154+
155+
return problem;
156+
},
157+
};
158+
};
159+
160+
const schema = [
161+
{
162+
type: 'object',
163+
properties: {
164+
useErrorIsError: {
165+
type: 'boolean',
166+
},
167+
strategy: {
168+
enum: [
169+
'loose',
170+
'strict',
171+
],
172+
},
173+
include: {
174+
type: 'array',
175+
items: {
176+
type: 'string',
177+
},
178+
},
179+
exclude: {
180+
type: 'array',
181+
items: {
182+
type: 'string',
183+
},
184+
},
185+
},
186+
additionalProperties: false,
187+
},
188+
];
189+
190+
/** @type {import('eslint').Rule.RuleModule} */
191+
const config = {
192+
create: checkVueTemplate(create),
193+
meta: {
194+
type: 'problem',
195+
docs: {
196+
description: 'Disallow `instanceof` with built-in objects',
197+
recommended: true,
198+
},
199+
fixable: 'code',
200+
schema,
201+
defaultOptions: [{
202+
useErrorIsError: false,
203+
strategy: 'loose',
204+
include: [],
205+
exclude: [],
206+
}],
207+
messages,
208+
},
209+
};
210+
211+
export default config;

‎rules/prevent-abbreviations.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path';
2+
import {isRegExp} from 'node:util/types';
23
import {defaultsDeep, upperFirst, lowerFirst} from './utils/lodash.js';
34
import avoidCapture from './utils/avoid-capture.js';
45
import cartesianProductSamples from './utils/cartesian-product-samples.js';
@@ -50,7 +51,7 @@ const prepareOptions = ({
5051
ignore = [...defaultIgnore, ...ignore];
5152

5253
ignore = ignore.map(
53-
pattern => pattern instanceof RegExp ? pattern : new RegExp(pattern, 'u'),
54+
pattern => isRegExp(pattern) ? pattern : new RegExp(pattern, 'u'),
5455
);
5556

5657
return {

‎rules/shared/builtin-errors.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const builtinErrors = [
2+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
3+
'Error',
4+
'EvalError',
5+
'RangeError',
6+
'ReferenceError',
7+
'SyntaxError',
8+
'TypeError',
9+
'URIError',
10+
'InternalError',
11+
'AggregateError',
12+
];
13+
14+
export default builtinErrors;

‎test/no-instanceof-builtin-object.js

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
import outdent from 'outdent';
2+
import {getTester, parsers} from './utils/test.js';
3+
4+
const {test} = getTester(import.meta);
5+
6+
const looseStrategyInvalid = [
7+
// Primitive types
8+
'foo instanceof String',
9+
'foo instanceof Number',
10+
'foo instanceof Boolean',
11+
'foo instanceof BigInt',
12+
'foo instanceof Symbol',
13+
'foo instanceof Function',
14+
'foo instanceof Array',
15+
];
16+
17+
const strictStrategyInvalid = [
18+
// Error types
19+
'foo instanceof Error',
20+
'foo instanceof EvalError',
21+
'foo instanceof RangeError',
22+
'foo instanceof ReferenceError',
23+
'foo instanceof SyntaxError',
24+
'foo instanceof TypeError',
25+
'foo instanceof URIError',
26+
'foo instanceof InternalError',
27+
'foo instanceof AggregateError',
28+
29+
// Collection types
30+
'foo instanceof Map',
31+
'foo instanceof Set',
32+
'foo instanceof WeakMap',
33+
'foo instanceof WeakRef',
34+
'foo instanceof WeakSet',
35+
36+
// Arrays and Typed Arrays
37+
'foo instanceof ArrayBuffer',
38+
'foo instanceof Int8Array',
39+
'foo instanceof Uint8Array',
40+
'foo instanceof Uint8ClampedArray',
41+
'foo instanceof Int16Array',
42+
'foo instanceof Uint16Array',
43+
'foo instanceof Int32Array',
44+
'foo instanceof Uint32Array',
45+
'foo instanceof Float32Array',
46+
'foo instanceof Float64Array',
47+
'foo instanceof BigInt64Array',
48+
'foo instanceof BigUint64Array',
49+
50+
// Data types
51+
'foo instanceof Object',
52+
53+
// Regular Expressions
54+
'foo instanceof RegExp',
55+
56+
// Async and functions
57+
'foo instanceof Promise',
58+
'foo instanceof Proxy',
59+
60+
// Other
61+
'foo instanceof DataView',
62+
'foo instanceof Date',
63+
'foo instanceof SharedArrayBuffer',
64+
'foo instanceof FinalizationRegistry',
65+
];
66+
67+
// Loose strategy
68+
test.snapshot({
69+
valid: [
70+
'foo instanceof WebWorker',
71+
...strictStrategyInvalid,
72+
].map(code => code.replace('foo', 'fooLoose')),
73+
invalid: looseStrategyInvalid,
74+
});
75+
76+
// Strict strategy
77+
test.snapshot({
78+
valid: [],
79+
invalid: [...looseStrategyInvalid, ...strictStrategyInvalid].map(code => ({code: code.replace('foo', 'fooStrict'), options: [{strategy: 'strict'}]})),
80+
});
81+
82+
// UseErrorIsError option with loose strategy
83+
test.snapshot({
84+
valid: [],
85+
invalid: [
86+
'fooErr instanceof Error',
87+
'(fooErr) instanceof (Error)',
88+
].map(code => ({code, options: [{useErrorIsError: true, strategy: 'loose'}]})),
89+
});
90+
91+
// UseErrorIsError option with strict strategy
92+
test.snapshot({
93+
valid: [],
94+
invalid: [
95+
'err instanceof Error',
96+
'err instanceof EvalError',
97+
'err instanceof RangeError',
98+
'err instanceof ReferenceError',
99+
'err instanceof SyntaxError',
100+
'err instanceof TypeError',
101+
'err instanceof URIError',
102+
'err instanceof InternalError',
103+
'err instanceof AggregateError',
104+
].map(code => ({code, options: [{useErrorIsError: true, strategy: 'strict'}]})),
105+
});
106+
107+
test.snapshot({
108+
valid: [
109+
// Exclude the specified constructors
110+
{
111+
code: 'fooExclude instanceof Function',
112+
options: [{exclude: ['Function']}],
113+
},
114+
{
115+
code: 'fooExclude instanceof Array',
116+
options: [{exclude: ['Array']}],
117+
},
118+
{
119+
code: 'fooExclude instanceof String',
120+
options: [{exclude: ['String']}],
121+
},
122+
],
123+
invalid: [
124+
// Include the specified constructors
125+
{
126+
code: 'fooInclude instanceof WebWorker',
127+
options: [{include: ['WebWorker']}],
128+
},
129+
{
130+
code: 'fooInclude instanceof HTMLElement',
131+
options: [{include: ['HTMLElement']}],
132+
},
133+
],
134+
});
135+
136+
// Port from no-instanceof-array
137+
test.snapshot({
138+
valid: [
139+
'Array.isArray(arr)',
140+
'arr instanceof array',
141+
'a instanceof \'array\'',
142+
'a instanceof ArrayA',
143+
'a.x[2] instanceof foo()',
144+
'Array.isArray([1,2,3]) === true',
145+
'"arr instanceof Array"',
146+
],
147+
invalid: [
148+
// Port from no-instanceof-array
149+
'arr instanceof Array',
150+
'[] instanceof Array',
151+
'[1,2,3] instanceof Array === true',
152+
'fun.call(1, 2, 3) instanceof Array',
153+
'obj.arr instanceof Array',
154+
'foo.bar[2] instanceof Array',
155+
'(0, array) instanceof Array',
156+
'function foo(){return[]instanceof Array}',
157+
outdent`
158+
(
159+
// comment
160+
((
161+
// comment
162+
(
163+
// comment
164+
foo
165+
// comment
166+
)
167+
// comment
168+
))
169+
// comment
170+
)
171+
// comment before instanceof\r instanceof
172+
173+
// comment after instanceof
174+
175+
(
176+
// comment
177+
178+
(
179+
180+
// comment
181+
182+
Array
183+
184+
// comment
185+
)
186+
187+
// comment
188+
)
189+
190+
// comment
191+
`,
192+
...[
193+
'<template><div v-if="array instanceof Array" v-for="element of array"></div></template>',
194+
'<template><div v-if="(( (( array )) instanceof (( Array )) ))" v-for="element of array"></div></template>',
195+
'<template><div>{{(( (( array )) instanceof (( Array )) )) ? array.join(" | ") : array}}</div></template>',
196+
'<script>const foo = array instanceof Array</script>',
197+
'<script>const foo = (( (( array )) instanceof (( Array )) ))</script>',
198+
'<script>foo instanceof Function</script>',
199+
].map(code => ({code, languageOptions: {parser: parsers.vue}})),
200+
],
201+
});

‎test/package.js

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const RULES_WITHOUT_PASS_FAIL_SECTIONS = new Set([
3333
'prefer-math-min-max',
3434
'consistent-existence-index-check',
3535
'prefer-global-this',
36+
'no-instanceof-builtin-object',
3637
]);
3738

3839
test('Every rule is defined in index file in alphabetical order', t => {

‎test/snapshots/no-instanceof-builtin-object.js.md

+2,018
Large diffs are not rendered by default.
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.