File tree Expand file tree Collapse file tree 4 files changed +148
-6
lines changed
compiler/packages/babel-plugin-react-compiler/src
__tests__/fixtures/compiler/ecma Expand file tree Collapse file tree 4 files changed +148
-6
lines changed Original file line number Diff line number Diff line change @@ -14,6 +14,7 @@ import type {HookKind} from './ObjectShape';
14
14
import { Type , makeType } from './Types' ;
15
15
import { z } from 'zod' ;
16
16
import type { AliasingEffect } from '../Inference/AliasingEffects' ;
17
+ import { isReservedWord } from '../Utils/Keyword' ;
17
18
18
19
/*
19
20
* *******************************************************************************************
@@ -1320,12 +1321,21 @@ export function forkTemporaryIdentifier(
1320
1321
* original source code.
1321
1322
*/
1322
1323
export function makeIdentifierName ( name : string ) : ValidatedIdentifier {
1323
- CompilerError . invariant ( t . isValidIdentifier ( name ) , {
1324
- reason : `Expected a valid identifier name` ,
1325
- loc : GeneratedSource ,
1326
- description : `\`${ name } \` is not a valid JavaScript identifier` ,
1327
- suggestions : null ,
1328
- } ) ;
1324
+ if ( isReservedWord ( name ) ) {
1325
+ CompilerError . throwInvalidJS ( {
1326
+ reason : 'Expected a non-reserved identifier name' ,
1327
+ loc : GeneratedSource ,
1328
+ description : `\`${ name } \` is a reserved word in JavaScript and cannot be used as an identifier name` ,
1329
+ suggestions : null ,
1330
+ } ) ;
1331
+ } else {
1332
+ CompilerError . invariant ( t . isValidIdentifier ( name ) , {
1333
+ reason : `Expected a valid identifier name` ,
1334
+ loc : GeneratedSource ,
1335
+ description : `\`${ name } \` is not a valid JavaScript identifier` ,
1336
+ suggestions : null ,
1337
+ } ) ;
1338
+ }
1329
1339
return {
1330
1340
kind : 'named' ,
1331
1341
value : name as ValidIdentifierName ,
Original file line number Diff line number Diff line change
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /**
9
+ * https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-keywords-and-reserved-words
10
+ */
11
+
12
+ /**
13
+ * Note: `await` and `yield` are contextually allowed as identifiers.
14
+ * await: reserved inside async functions and modules
15
+ * yield: reserved inside generator functions
16
+ *
17
+ * Note: `async` is not reserved.
18
+ */
19
+ const RESERVED_WORDS = new Set ( [
20
+ 'break' ,
21
+ 'case' ,
22
+ 'catch' ,
23
+ 'class' ,
24
+ 'const' ,
25
+ 'continue' ,
26
+ 'debugger' ,
27
+ 'default' ,
28
+ 'delete' ,
29
+ 'do' ,
30
+ 'else' ,
31
+ 'enum' ,
32
+ 'export' ,
33
+ 'extends' ,
34
+ 'false' ,
35
+ 'finally' ,
36
+ 'for' ,
37
+ 'function' ,
38
+ 'if' ,
39
+ 'import' ,
40
+ 'in' ,
41
+ 'instanceof' ,
42
+ 'new' ,
43
+ 'null' ,
44
+ 'return' ,
45
+ 'super' ,
46
+ 'switch' ,
47
+ 'this' ,
48
+ 'throw' ,
49
+ 'true' ,
50
+ 'try' ,
51
+ 'typeof' ,
52
+ 'var' ,
53
+ 'void' ,
54
+ 'while' ,
55
+ 'with' ,
56
+ ] ) ;
57
+
58
+ /**
59
+ * Reserved when a module has a 'use strict' directive.
60
+ */
61
+ const STRICT_MODE_RESERVED_WORDS = new Set ( [
62
+ 'let' ,
63
+ 'static' ,
64
+ 'implements' ,
65
+ 'interface' ,
66
+ 'package' ,
67
+ 'private' ,
68
+ 'protected' ,
69
+ 'public' ,
70
+ ] ) ;
71
+ /**
72
+ * The names arguments and eval are not keywords, but they are subject to some restrictions in
73
+ * strict mode code.
74
+ */
75
+ const STRICT_MODE_RESTRICTED_WORDS = new Set ( [ 'eval' , 'arguments' ] ) ;
76
+
77
+ /**
78
+ * Conservative check for whether an identifer name is reserved or not. We assume that code is
79
+ * written with strict mode.
80
+ */
81
+ export function isReservedWord ( identifierName : string ) : boolean {
82
+ return (
83
+ RESERVED_WORDS . has ( identifierName ) ||
84
+ STRICT_MODE_RESERVED_WORDS . has ( identifierName ) ||
85
+ STRICT_MODE_RESTRICTED_WORDS . has ( identifierName )
86
+ ) ;
87
+ }
Original file line number Diff line number Diff line change
1
+
2
+ ## Input
3
+
4
+ ``` javascript
5
+ import {useRef } from ' react' ;
6
+
7
+ function useThing (fn ) {
8
+ const fnRef = useRef (fn);
9
+ const ref = useRef (null );
10
+
11
+ if (ref .current === null ) {
12
+ ref .current = function (this : unknown , ... args ) {
13
+ return fnRef .current .call (this , ... args);
14
+ };
15
+ }
16
+ return ref .current ;
17
+ }
18
+
19
+ ```
20
+
21
+
22
+ ## Error
23
+
24
+ ```
25
+ Found 1 error:
26
+
27
+ Error: Expected a non-reserved identifier name
28
+
29
+ `this` is a reserved word in JavaScript and cannot be used as an identifier name.
30
+ ```
31
+
32
+
Original file line number Diff line number Diff line change
1
+ import { useRef } from 'react' ;
2
+
3
+ function useThing ( fn ) {
4
+ const fnRef = useRef ( fn ) ;
5
+ const ref = useRef ( null ) ;
6
+
7
+ if ( ref . current === null ) {
8
+ ref . current = function ( this : unknown , ...args ) {
9
+ return fnRef . current . call ( this , ...args ) ;
10
+ } ;
11
+ }
12
+ return ref . current ;
13
+ }
You can’t perform that action at this time.
0 commit comments