Skip to content

Commit a4e89db

Browse files
feat: no-obj-calls support Intl (#16543)
* feat: support `Intl` * test: add tests for `Intl` * docs: update docs for `Intl` * docs: update docs/src/rules/no-obj-calls.md Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
1 parent a01315a commit a4e89db

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

docs/src/rules/no-obj-calls.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@ The [ECMAScript 2015 specification](https://www.ecma-international.org/ecma-262/
1717

1818
> The Reflect object also does not have a `[[Call]]` internal method; it is not possible to invoke the Reflect object as a function.
1919
20-
And the [ECMAScript 2017 specification](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-atomics-object) makes it clear that `Atomics` cannot be invoked:
20+
The [ECMAScript 2017 specification](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-atomics-object) makes it clear that `Atomics` cannot be invoked:
2121

2222
> The Atomics object does not have a `[[Call]]` internal method; it is not possible to invoke the Atomics object as a function.
2323
24+
And the [ECMAScript Internationalization API Specification](https://tc39.es/ecma402/#intl-object) makes it clear that `Intl` cannot be invoked:
25+
26+
> The Intl object does not have a `[[Call]]` internal method; it is not possible to invoke the Intl object as a function.
27+
2428
## Rule Details
2529

26-
This rule disallows calling the `Math`, `JSON`, `Reflect` and `Atomics` objects as functions.
30+
This rule disallows calling the `Math`, `JSON`, `Reflect`, `Atomics` and `Intl` objects as functions.
2731

2832
This rule also disallows using these objects as constructors with the `new` operator.
2933

@@ -33,7 +37,7 @@ Examples of **incorrect** code for this rule:
3337

3438
```js
3539
/*eslint no-obj-calls: "error"*/
36-
/*eslint-env es2017*/
40+
/*eslint-env es2017, browser */
3741

3842
var math = Math();
3943

@@ -50,6 +54,10 @@ var newReflect = new Reflect();
5054
var atomics = Atomics();
5155

5256
var newAtomics = new Atomics();
57+
58+
var intl = Intl();
59+
60+
var newIntl = new Intl();
5361
```
5462

5563
:::
@@ -60,7 +68,7 @@ Examples of **correct** code for this rule:
6068

6169
```js
6270
/*eslint no-obj-calls: "error"*/
63-
/*eslint-env es2017*/
71+
/*eslint-env es2017, browser*/
6472

6573
function area(r) {
6674
return Math.PI * r * r;
@@ -71,6 +79,8 @@ var object = JSON.parse("{}");
7179
var value = Reflect.get({ x: 1, y: 2 }, "x");
7280

7381
var first = Atomics.load(foo, 0);
82+
83+
var segmenterFr = new Intl.Segmenter("fr", { granularity: "word" });
7484
```
7585

7686
:::

lib/rules/no-obj-calls.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const getPropertyName = require("./utils/ast-utils").getStaticPropertyName;
1616
// Helpers
1717
//------------------------------------------------------------------------------
1818

19-
const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect"];
19+
const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect", "Intl"];
2020

2121
/**
2222
* Returns the name of the node to report

tests/lib/rules/no-obj-calls.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ ruleTester.run("no-obj-calls", rule, {
4545
code: "new Atomics.foo()",
4646
env: { es2017: true }
4747
},
48+
{
49+
code: "new Intl.Segmenter()",
50+
env: { browser: true }
51+
},
52+
{
53+
code: "Intl.foo()",
54+
env: { browser: true }
55+
},
4856

4957
{ code: "globalThis.Math();", env: { es6: true } },
5058
{ code: "var x = globalThis.Math();", env: { es6: true } },
@@ -58,6 +66,8 @@ ruleTester.run("no-obj-calls", rule, {
5866
{ code: "/*globals Reflect: true*/ globalThis.Reflect();", env: { es2017: true } },
5967
{ code: "var x = globalThis.Atomics();", env: { es2017: true } },
6068
{ code: "var x = globalThis.Atomics();", globals: { Atomics: false }, env: { es2017: true } },
69+
{ code: "var x = globalThis.Intl();", env: { browser: true } },
70+
{ code: "var x = globalThis.Intl();", globals: { Intl: false }, env: { browser: true } },
6171

6272
// non-existing variables
6373
"/*globals Math: off*/ Math();",
@@ -78,6 +88,8 @@ ruleTester.run("no-obj-calls", rule, {
7888
code: "Atomics();",
7989
env: { es6: true }
8090
},
91+
"Intl()",
92+
"new Intl()",
8193

8294
// shadowed variables
8395
"var Math; Math();",
@@ -119,6 +131,20 @@ ruleTester.run("no-obj-calls", rule, {
119131
{
120132
code: "var construct = typeof Reflect !== \"undefined\" ? Reflect.construct : undefined; construct();",
121133
globals: { Reflect: false }
134+
},
135+
{
136+
code: "function foo(Intl) { Intl(); }",
137+
env: { browser: true }
138+
},
139+
{
140+
code: "if (foo) { const Intl = 1; Intl(); }",
141+
parserOptions: { ecmaVersion: 2015 },
142+
env: { browser: true }
143+
},
144+
{
145+
code: "if (foo) { const Intl = 1; new Intl(); }",
146+
parserOptions: { ecmaVersion: 2015 },
147+
env: { browser: true }
122148
}
123149
],
124150
invalid: [
@@ -225,6 +251,24 @@ ruleTester.run("no-obj-calls", rule, {
225251
globals: { Atomics: "writable" },
226252
errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "NewExpression" }]
227253
},
254+
{
255+
code: "var x = Intl();",
256+
env: { browser: true },
257+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "CallExpression" }]
258+
},
259+
{
260+
code: "var x = new Intl();",
261+
env: { browser: true },
262+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "NewExpression" }]
263+
},
264+
{
265+
code: "/*globals Intl: true*/ Intl();",
266+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "CallExpression" }]
267+
},
268+
{
269+
code: "/*globals Intl: true*/ new Intl();",
270+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "NewExpression" }]
271+
},
228272
{
229273
code: "var x = globalThis.Math();",
230274
env: { es2020: true },
@@ -288,6 +332,21 @@ ruleTester.run("no-obj-calls", rule, {
288332
env: { es2020: true },
289333
errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }]
290334
},
335+
{
336+
code: "var x = globalThis.Intl();",
337+
env: { browser: true, es2020: true },
338+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "CallExpression" }]
339+
},
340+
{
341+
code: "var x = new globalThis.Intl;",
342+
env: { browser: true, es2020: true },
343+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "NewExpression" }]
344+
},
345+
{
346+
code: "/*globals Intl: true*/ Intl();",
347+
env: { browser: true, es2020: true },
348+
errors: [{ messageId: "unexpectedCall", data: { name: "Intl" }, type: "CallExpression" }]
349+
},
291350
{
292351
code: "var foo = bar ? baz: JSON; foo();",
293352
errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "JSON" }, type: "CallExpression" }]
@@ -316,6 +375,16 @@ ruleTester.run("no-obj-calls", rule, {
316375
env: { es2020: true, browser: true },
317376
errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "Atomics" }, type: "NewExpression" }]
318377
},
378+
{
379+
code: "var foo = window.Intl; foo();",
380+
env: { es2020: true, browser: true },
381+
errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "Intl" }, type: "CallExpression" }]
382+
},
383+
{
384+
code: "var foo = window.Intl; new foo;",
385+
env: { es2020: true, browser: true },
386+
errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "Intl" }, type: "NewExpression" }]
387+
},
319388

320389
// Optional chaining
321390
{

0 commit comments

Comments
 (0)