1use std::{
2    borrow::Cow,
3    fmt::Display,
4    ops::{Deref, DerefMut},
5};
6
7use once_cell::sync::Lazy;
8use phf::phf_set;
9use rustc_hash::FxHashSet;
10use swc_atoms::{atom, Atom, UnsafeAtom};
11use swc_common::{
12    ast_node, util::take::Take, BytePos, EqIgnoreSpan, Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
13};
14
15use crate::{typescript::TsTypeAnn, Expr};
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan, Default)]
19#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
20#[cfg_attr(
21    any(feature = "rkyv-impl"),
22    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
23)]
24#[cfg_attr(
25    feature = "rkyv-impl",
26    rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
27        __S::Error: rkyv::rancor::Source))
28)]
29#[cfg_attr(
30    feature = "rkyv-impl",
31    rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))
32)]
33#[cfg_attr(
34    feature = "rkyv-impl",
35    rkyv(bytecheck(bounds(
36        __C: rkyv::validation::ArchiveContext,
37        __C::Error: rkyv::rancor::Source
38    )))
39)]
40#[cfg_attr(feature = "rkyv-impl", repr(C))]
41#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
42#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
43#[cfg_attr(
44    feature = "encoding-impl",
45    derive(::swc_common::Encode, ::swc_common::Decode)
46)]
47pub struct BindingIdent {
48    #[cfg_attr(feature = "serde-impl", serde(flatten))]
49    #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))]
50    pub id: Ident,
51
52    #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
53    #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))]
54    #[cfg_attr(
55        feature = "encoding-impl",
56        encoding(with = "cbor4ii::core::types::Maybe")
57    )]
58    pub type_ann: Option<Box<TsTypeAnn>>,
59}
60
61impl Spanned for BindingIdent {
62    fn span(&self) -> Span {
63        match &self.type_ann {
64            Some(ann) => Span::new(self.id.span.lo(), ann.span().hi()),
65            None => self.id.span,
66        }
67    }
68}
69
70impl Deref for BindingIdent {
71    type Target = Ident;
72
73    fn deref(&self) -> &Self::Target {
74        &self.id
75    }
76}
77
78impl DerefMut for BindingIdent {
79    fn deref_mut(&mut self) -> &mut Self::Target {
80        &mut self.id
81    }
82}
83
84impl AsRef<str> for BindingIdent {
85    fn as_ref(&self) -> &str {
86        &self.sym
87    }
88}
89
90impl From<BindingIdent> for Box<Expr> {
91    fn from(bi: BindingIdent) -> Self {
92        Box::new(Expr::Ident(bi.into()))
93    }
94}
95impl From<&'_ BindingIdent> for Ident {
96    fn from(bi: &'_ BindingIdent) -> Self {
97        Ident {
98            span: bi.span,
99            ctxt: bi.ctxt,
100            sym: bi.sym.clone(),
101            optional: bi.optional,
102        }
103    }
104}
105
106impl BindingIdent {
107    pub fn to_id(&self) -> Id {
109        (self.sym.clone(), self.ctxt)
110    }
111}
112
113impl Take for BindingIdent {
114    fn dummy() -> Self {
115        Default::default()
116    }
117}
118
119impl From<Ident> for BindingIdent {
120    fn from(id: Ident) -> Self {
121        BindingIdent {
122            id,
123            ..Default::default()
124        }
125    }
126}
127
128bridge_from!(BindingIdent, Ident, Id);
129
130#[ast_node("Identifier")]
181#[derive(Eq, Hash, Default)]
182#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
183pub struct Ident {
184    #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))]
185    pub span: Span,
186
187    #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))]
188    pub ctxt: SyntaxContext,
189
190    #[cfg_attr(feature = "serde-impl", serde(rename = "value"))]
191    pub sym: Atom,
192
193    #[cfg_attr(feature = "serde-impl", serde(default))]
195    pub optional: bool,
196}
197
198impl From<BindingIdent> for Ident {
199    fn from(bi: BindingIdent) -> Self {
200        bi.id
201    }
202}
203
204impl From<Atom> for Ident {
205    fn from(bi: Atom) -> Self {
206        Ident::new_no_ctxt(bi, DUMMY_SP)
207    }
208}
209bridge_from!(Ident, Atom, &'_ str);
210bridge_from!(Ident, Atom, Cow<'_, str>);
211bridge_from!(Ident, Atom, String);
212
213impl From<(Atom, Span)> for Ident {
214    fn from((sym, span): (Atom, Span)) -> Self {
215        Ident {
216            span,
217            sym,
218            ..Default::default()
219        }
220    }
221}
222
223impl EqIgnoreSpan for Ident {
224    fn eq_ignore_span(&self, other: &Self) -> bool {
225        if self.sym != other.sym {
226            return false;
227        }
228
229        self.ctxt.eq_ignore_span(&other.ctxt)
230    }
231}
232
233impl From<Id> for Ident {
234    fn from(id: Id) -> Self {
235        Ident::new(id.0, DUMMY_SP, id.1)
236    }
237}
238
239impl From<Ident> for Id {
240    fn from(i: Ident) -> Self {
241        (i.sym, i.ctxt)
242    }
243}
244
245#[repr(C, align(64))]
246struct Align64<T>(pub(crate) T);
247
248const T: bool = true;
249const F: bool = false;
250
251impl Ident {
252    pub fn within_ignored_ctxt<F, Ret>(op: F) -> Ret
254    where
255        F: FnOnce() -> Ret,
256    {
257        SyntaxContext::within_ignored_ctxt(op)
258    }
259
260    pub fn without_loc(mut self) -> Ident {
262        self.span.lo = BytePos::DUMMY;
263        self.span.hi = BytePos::DUMMY;
264        self
265    }
266
267    pub fn to_id(&self) -> Id {
269        (self.sym.clone(), self.ctxt)
270    }
271
272    #[inline]
273    pub fn is_valid_ascii_start(c: u8) -> bool {
274        debug_assert!(c.is_ascii());
275        const ASCII_START: Align64<[bool; 128]> = Align64([
277            F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F,
278            F, F, F, F, F, F, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F,
279            F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
280            T, T, T, T, F, F, F, F, T, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
281            T, T, T, T, T, T, T, F, F, F, F, F,
282        ]);
283        ASCII_START.0[c as usize]
284    }
285
286    pub fn is_valid_non_ascii_start(c: char) -> bool {
287        debug_assert!(!c.is_ascii());
288        unicode_id_start::is_id_start_unicode(c)
289    }
290
291    #[inline]
293    pub fn is_valid_start(c: char) -> bool {
294        if c.is_ascii() {
295            Self::is_valid_ascii_start(c as u8)
296        } else {
297            Self::is_valid_non_ascii_start(c)
298        }
299    }
300
301    #[inline]
302    pub fn is_valid_non_ascii_continue(c: char) -> bool {
303        debug_assert!(!c.is_ascii());
304        unicode_id_start::is_id_continue_unicode(c)
305    }
306
307    #[inline]
308    pub fn is_valid_ascii_continue(c: u8) -> bool {
309        debug_assert!(c.is_ascii());
310        const ASCII_CONTINUE: Align64<[bool; 128]> = Align64([
312            F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F,
313            F, F, F, F, F, F, F, T, F, F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T,
314            F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
315            T, T, T, T, F, F, F, F, T, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
316            T, T, T, T, T, T, T, F, F, F, F, F,
317        ]);
318        ASCII_CONTINUE.0[c as usize]
319    }
320
321    #[inline]
324    pub fn is_valid_continue(c: char) -> bool {
325        if c.is_ascii() {
326            Self::is_valid_ascii_continue(c as u8)
327        } else {
328            Self::is_valid_non_ascii_continue(c)
329        }
330    }
331
332    pub fn verify_symbol(s: &str) -> Result<(), String> {
337        fn is_reserved_symbol(s: &str) -> bool {
338            s.is_reserved() || s.is_reserved_in_strict_mode(true) || s.is_reserved_in_strict_bind()
339        }
340
341        if is_reserved_symbol(s) {
342            let mut buf = String::with_capacity(s.len() + 1);
343            buf.push('_');
344            buf.push_str(s);
345            return Err(buf);
346        }
347
348        {
349            let mut chars = s.chars();
350
351            if let Some(first) = chars.next() {
352                if Self::is_valid_start(first) && chars.all(Self::is_valid_continue) {
353                    return Ok(());
354                }
355            }
356        }
357
358        let mut buf = String::with_capacity(s.len() + 2);
359        let mut has_start = false;
360
361        for c in s.chars() {
362            if !has_start && Self::is_valid_start(c) {
363                has_start = true;
364                buf.push(c);
365                continue;
366            }
367
368            if Self::is_valid_continue(c) {
369                buf.push(c);
370            }
371        }
372
373        if buf.is_empty() {
374            buf.push('_');
375        }
376
377        if is_reserved_symbol(&buf) {
378            let mut new_buf = String::with_capacity(buf.len() + 1);
379            new_buf.push('_');
380            new_buf.push_str(&buf);
381            buf = new_buf;
382        }
383
384        Err(buf)
385    }
386
387    pub fn with_prefix(&self, prefix: &str) -> Ident {
389        Ident::new(
390            format!("{}{}", prefix, self.sym).into(),
391            self.span,
392            self.ctxt,
393        )
394    }
395
396    pub fn into_private(self) -> Ident {
399        Self::new(
400            self.sym,
401            self.span,
402            SyntaxContext::empty().apply_mark(Mark::new()),
403        )
404    }
405
406    #[inline]
407    pub fn is_dummy(&self) -> bool {
408        self.sym == atom!("") && self.span.is_dummy()
409    }
410
411    pub fn with_pos(mut self, lo: BytePos, hi: BytePos) -> Ident {
413        self.span = Span::new(lo, hi);
414        self
415    }
416}
417
418#[ast_node("Identifier")]
419#[derive(Eq, Hash, Default, EqIgnoreSpan)]
420#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
421#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
422pub struct IdentName {
423    #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))]
424    pub span: Span,
425
426    #[cfg_attr(feature = "serde-impl", serde(rename = "value"))]
427    pub sym: Atom,
428}
429
430impl From<Atom> for IdentName {
431    fn from(sym: Atom) -> Self {
432        IdentName {
433            span: DUMMY_SP,
434            sym,
435        }
436    }
437}
438
439impl From<(Atom, Span)> for IdentName {
440    fn from((sym, span): (Atom, Span)) -> Self {
441        IdentName { span, sym }
442    }
443}
444
445bridge_from!(IdentName, Atom, &'_ str);
446bridge_from!(IdentName, Atom, Cow<'_, str>);
447bridge_from!(IdentName, Atom, String);
448bridge_from!(IdentName, Ident, &'_ BindingIdent);
449bridge_from!(IdentName, Ident, BindingIdent);
450
451impl AsRef<str> for IdentName {
452    fn as_ref(&self) -> &str {
453        &self.sym
454    }
455}
456
457impl IdentName {
458    pub const fn new(sym: Atom, span: Span) -> Self {
459        Self { span, sym }
460    }
461}
462
463impl Take for IdentName {
464    fn dummy() -> Self {
465        Default::default()
466    }
467}
468
469impl From<Ident> for IdentName {
470    fn from(i: Ident) -> Self {
471        IdentName {
472            span: i.span,
473            sym: i.sym,
474        }
475    }
476}
477
478impl From<IdentName> for Ident {
479    fn from(i: IdentName) -> Self {
480        Ident {
481            span: i.span,
482            sym: i.sym,
483            ..Default::default()
484        }
485    }
486}
487
488bridge_from!(BindingIdent, Ident, Atom);
489bridge_from!(BindingIdent, Atom, &'_ str);
490bridge_from!(BindingIdent, Atom, Cow<'_, str>);
491bridge_from!(BindingIdent, Atom, String);
492
493impl From<IdentName> for BindingIdent {
494    fn from(i: IdentName) -> Self {
495        BindingIdent {
496            id: i.into(),
497            ..Default::default()
498        }
499    }
500}
501
502pub type UnsafeId = (UnsafeAtom, SyntaxContext);
510
511pub unsafe fn unsafe_id(id: &Id) -> UnsafeId {
520    (UnsafeAtom::new(&id.0), id.1)
521}
522
523pub unsafe fn unsafe_id_from_ident(id: &Ident) -> UnsafeId {
532    (UnsafeAtom::new(&id.sym), id.ctxt)
533}
534
535pub type Id = (Atom, SyntaxContext);
537
538impl Take for Ident {
539    fn dummy() -> Self {
540        Ident::new_no_ctxt(atom!(""), DUMMY_SP)
541    }
542}
543
544impl Display for Ident {
545    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
546        write!(f, "{}{:?}", self.sym, self.ctxt)
547    }
548}
549
550impl Display for IdentName {
551    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552        write!(f, "{}", self.sym)
553    }
554}
555
556impl Display for BindingIdent {
557    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
558        write!(f, "{}{:?}", self.sym, self.ctxt)
559    }
560}
561
562#[cfg(feature = "arbitrary")]
563#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
564impl<'a> arbitrary::Arbitrary<'a> for Ident {
565    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
566        let span = u.arbitrary()?;
567        let sym = u.arbitrary::<Atom>()?;
568
569        let optional = u.arbitrary()?;
570
571        Ok(Self {
572            span,
573            sym,
574            optional,
575            ctxt: Default::default(),
576        })
577    }
578}
579
580#[ast_node("PrivateName")]
581#[derive(Eq, Hash, EqIgnoreSpan, Default)]
582#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
583#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
584pub struct PrivateName {
585    pub span: Span,
586    #[cfg_attr(feature = "serde-impl", serde(rename = "value"))]
587    pub name: Atom,
588}
589
590impl AsRef<str> for Ident {
591    fn as_ref(&self) -> &str {
592        &self.sym
593    }
594}
595
596impl Ident {
597    pub const fn new(sym: Atom, span: Span, ctxt: SyntaxContext) -> Self {
598        Ident {
599            span,
600            ctxt,
601            sym,
602            optional: false,
603        }
604    }
605
606    #[inline(never)]
615    pub fn new_private(sym: Atom, span: Span) -> Self {
616        Self::new(sym, span, SyntaxContext::empty().apply_mark(Mark::new()))
617    }
618
619    pub const fn new_no_ctxt(sym: Atom, span: Span) -> Self {
620        Self::new(sym, span, SyntaxContext::empty())
621    }
622}
623
624macro_rules! gen_reserved_set {
625    ($set: ident, $set_atoms: ident, [$($item: expr),*]) => {
626        static $set: phf::Set<&str> = phf_set!($($item),*);
627        static $set_atoms: Lazy<FxHashSet<Atom>> = Lazy::new(|| {
628            let mut set = FxHashSet::with_capacity_and_hasher($set.len(), rustc_hash::FxBuildHasher);
629            $(
630                set.insert(atom!($item));
631            )*
632            set
633        });
634    };
635}
636
637gen_reserved_set!(
638    RESERVED,
639    RESERVED_ATOMS,
640    [
641        "break",
642        "case",
643        "catch",
644        "class",
645        "const",
646        "continue",
647        "debugger",
648        "default",
649        "delete",
650        "do",
651        "else",
652        "enum",
653        "export",
654        "extends",
655        "false",
656        "finally",
657        "for",
658        "function",
659        "if",
660        "import",
661        "in",
662        "instanceof",
663        "new",
664        "null",
665        "package",
666        "return",
667        "super",
668        "switch",
669        "this",
670        "throw",
671        "true",
672        "try",
673        "typeof",
674        "var",
675        "void",
676        "while",
677        "with"
678    ]
679);
680
681gen_reserved_set!(
682    RESSERVED_IN_STRICT_MODE,
683    RESSERVED_IN_STRICT_MODE_ATOMS,
684    [
685        "implements",
686        "interface",
687        "let",
688        "package",
689        "private",
690        "protected",
691        "public",
692        "static",
693        "yield"
694    ]
695);
696
697gen_reserved_set!(
698    RESSERVED_IN_STRICT_BIND,
699    RESSERVED_IN_STRICT_BIND_ATOMS,
700    ["eval", "arguments"]
701);
702
703gen_reserved_set!(
704    RESERVED_IN_ES3,
705    RESERVED_IN_ES3_ATOMS,
706    [
707        "abstract",
708        "boolean",
709        "byte",
710        "char",
711        "double",
712        "final",
713        "float",
714        "goto",
715        "int",
716        "long",
717        "native",
718        "short",
719        "synchronized",
720        "throws",
721        "transient",
722        "volatile"
723    ]
724);
725
726pub trait EsReserved {
727    fn is_reserved(&self) -> bool;
728    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool;
729    fn is_reserved_in_strict_bind(&self) -> bool;
730    fn is_reserved_in_es3(&self) -> bool;
731    fn is_reserved_in_any(&self) -> bool;
732}
733
734impl EsReserved for Atom {
735    fn is_reserved(&self) -> bool {
736        is_reserved_for_atom(self)
737    }
738
739    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
740        is_reserved_in_strict_mode_for_atom(self, is_module)
741    }
742
743    fn is_reserved_in_strict_bind(&self) -> bool {
744        is_reserved_in_strict_bind_for_atom(self)
745    }
746
747    fn is_reserved_in_es3(&self) -> bool {
748        is_reserved_in_es3_for_atom(self)
749    }
750
751    fn is_reserved_in_any(&self) -> bool {
752        is_reserved_in_any_for_atom(self)
753    }
754}
755impl EsReserved for IdentName {
756    fn is_reserved(&self) -> bool {
757        is_reserved_for_atom(&self.sym)
758    }
759
760    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
761        is_reserved_in_strict_mode_for_atom(&self.sym, is_module)
762    }
763
764    fn is_reserved_in_strict_bind(&self) -> bool {
765        is_reserved_in_strict_bind_for_atom(&self.sym)
766    }
767
768    fn is_reserved_in_es3(&self) -> bool {
769        is_reserved_in_es3_for_atom(&self.sym)
770    }
771
772    fn is_reserved_in_any(&self) -> bool {
773        is_reserved_in_any_for_atom(&self.sym)
774    }
775}
776impl EsReserved for Ident {
777    fn is_reserved(&self) -> bool {
778        is_reserved_for_atom(&self.sym)
779    }
780
781    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
782        is_reserved_in_strict_mode_for_atom(&self.sym, is_module)
783    }
784
785    fn is_reserved_in_strict_bind(&self) -> bool {
786        is_reserved_in_strict_bind_for_atom(&self.sym)
787    }
788
789    fn is_reserved_in_es3(&self) -> bool {
790        is_reserved_in_es3_for_atom(&self.sym)
791    }
792
793    fn is_reserved_in_any(&self) -> bool {
794        is_reserved_in_any_for_atom(&self.sym)
795    }
796}
797impl EsReserved for BindingIdent {
798    fn is_reserved(&self) -> bool {
799        is_reserved_for_atom(&self.sym)
800    }
801
802    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
803        is_reserved_in_strict_mode_for_atom(&self.sym, is_module)
804    }
805
806    fn is_reserved_in_strict_bind(&self) -> bool {
807        is_reserved_in_strict_bind_for_atom(&self.sym)
808    }
809
810    fn is_reserved_in_es3(&self) -> bool {
811        is_reserved_in_es3_for_atom(&self.sym)
812    }
813
814    fn is_reserved_in_any(&self) -> bool {
815        is_reserved_in_any_for_atom(&self.sym)
816    }
817}
818impl EsReserved for &'_ str {
819    fn is_reserved(&self) -> bool {
820        is_reserved_for_str(self)
821    }
822
823    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
824        is_reserved_in_strict_mode_for_str(self, is_module)
825    }
826
827    fn is_reserved_in_strict_bind(&self) -> bool {
828        is_reserved_in_strict_bind_for_str(self)
829    }
830
831    fn is_reserved_in_es3(&self) -> bool {
832        is_reserved_in_es3_for_str(self)
833    }
834
835    fn is_reserved_in_any(&self) -> bool {
836        is_reserved_in_any_for_str(self)
837    }
838}
839impl EsReserved for String {
840    fn is_reserved(&self) -> bool {
841        is_reserved_for_str(self)
842    }
843
844    fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
845        is_reserved_in_strict_mode_for_str(self, is_module)
846    }
847
848    fn is_reserved_in_strict_bind(&self) -> bool {
849        is_reserved_in_strict_bind_for_str(self)
850    }
851
852    fn is_reserved_in_es3(&self) -> bool {
853        is_reserved_in_es3_for_str(self)
854    }
855
856    fn is_reserved_in_any(&self) -> bool {
857        is_reserved_in_any_for_str(self)
858    }
859}
860
861fn is_reserved_for_str(n: impl AsRef<str>) -> bool {
862    RESERVED.contains(n.as_ref())
863}
864
865fn is_reserved_in_strict_mode_for_str(n: impl AsRef<str>, is_module: bool) -> bool {
866    if is_module && n.as_ref() == "await" {
867        return true;
868    }
869    RESSERVED_IN_STRICT_MODE.contains(n.as_ref())
870}
871
872fn is_reserved_in_strict_bind_for_str(n: impl AsRef<str>) -> bool {
873    RESSERVED_IN_STRICT_BIND.contains(n.as_ref())
874}
875
876fn is_reserved_in_es3_for_str(n: impl AsRef<str>) -> bool {
877    RESERVED_IN_ES3.contains(n.as_ref())
878}
879
880fn is_reserved_in_any_for_str(n: impl AsRef<str>) -> bool {
881    RESERVED.contains(n.as_ref())
882        || RESSERVED_IN_STRICT_MODE.contains(n.as_ref())
883        || RESSERVED_IN_STRICT_BIND.contains(n.as_ref())
884        || RESERVED_IN_ES3.contains(n.as_ref())
885}
886
887fn is_reserved_for_atom(n: &Atom) -> bool {
888    RESERVED_ATOMS.contains(n)
889}
890
891fn is_reserved_in_strict_mode_for_atom(n: &Atom, is_module: bool) -> bool {
892    if is_module && *n == atom!("await") {
893        return true;
894    }
895    RESSERVED_IN_STRICT_MODE_ATOMS.contains(n)
896}
897
898fn is_reserved_in_strict_bind_for_atom(n: &Atom) -> bool {
899    RESSERVED_IN_STRICT_BIND_ATOMS.contains(n)
900}
901
902fn is_reserved_in_es3_for_atom(n: &Atom) -> bool {
903    RESERVED_IN_ES3_ATOMS.contains(n)
904}
905
906fn is_reserved_in_any_for_atom(n: &Atom) -> bool {
907    RESERVED_ATOMS.contains(n)
908        || RESSERVED_IN_STRICT_MODE_ATOMS.contains(n)
909        || RESSERVED_IN_STRICT_BIND_ATOMS.contains(n)
910        || RESERVED_IN_ES3_ATOMS.contains(n)
911}