Coverage Report

Created: 2025-12-12 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hermes/include/hermes/AST/SemValidate.h
Line
Count
Source
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
#ifndef HERMES_AST_SEMVALIDATE_H
9
#define HERMES_AST_SEMVALIDATE_H
10
11
#include "hermes/AST/Context.h"
12
#include "hermes/AST/ESTree.h"
13
#include "hermes/FrontEndDefs/JavaScriptDeclKind.h"
14
#include "hermes/Support/SourceErrorManager.h"
15
16
#include <deque>
17
18
namespace hermes {
19
namespace sem {
20
21
/// Semantic information for a function declaration, expression, method, etc.
22
class FunctionInfo {
23
 public:
24
  struct VarDecl {
25
    using Kind = JavaScriptDeclKind;
26
27
    Kind kind;
28
    ESTree::IdentifierNode *identifier;
29
30
    /// If false, this VarDecl does not need a default undefined/empty
31
    /// initialization. These are useful for VarDecls for functions.
32
    bool needsInitializer;
33
34
    /// Constructs a VarDecl with the given kind \p k and name \p id. The
35
    /// created VarDecl needsInitializer.
36
    VarDecl(Kind k, ESTree::IdentifierNode *id)
37
23.1k
        : kind(k), identifier(id), needsInitializer(true) {}
38
39
    /// Named-constructor for creating VarDecls that don't require initializers.
40
    static VarDecl withoutInitializer(
41
        Kind k,
42
0
        ESTree::IdentifierNode *identifier) {
43
0
      VarDecl v{k, identifier};
44
0
      v.needsInitializer = false;
45
0
      return v;
46
0
    }
47
  };
48
49
  using BlockDecls = llvh::SmallVector<VarDecl, 4>;
50
51
  /// Parameter names.
52
  BlockDecls paramNames{};
53
54
  /// This function's "var" declarations.
55
  BlockDecls varScoped;
56
57
  /// Map from AST Node to its lexical (let/const) declarations.
58
  llvh::DenseMap<ESTree::Node *, std::unique_ptr<BlockDecls>> lexicallyScoped{};
59
60
  using BlockClosures = llvh::SmallVector<ESTree::FunctionDeclarationNode *, 2>;
61
  /// Map from AST Node to the functions defined in it.
62
  llvh::DenseMap<ESTree::Node *, std::unique_ptr<BlockClosures>> closures{};
63
64
  /// A list of imports that need to be hoisted and materialized before we
65
  /// can generate the rest of the function.
66
  /// Any line of the file may use the imported values.
67
  llvh::SmallVector<ESTree::ImportDeclarationNode *, 2> imports{};
68
69
  /// Whether this function references the "arguments" identifier. This is a
70
  /// conservative approximation of whether it tries to access the "arguments"
71
  /// object. Why "conservative"? Because in non-strict mode it is possible to
72
  /// declare a variable called "arguments" and then access it.
73
  /// In the future, when we start resolving variables in the validator, we will
74
  /// be able to be completely accurate, but for now this is good enough.
75
  bool usesArguments = false;
76
77
  /// Whether this function contains arrow functions.
78
  bool containsArrowFunctions = false;
79
80
  /// This is a logical or of the \c usesArguments flags of all contained
81
  /// arrow functions. This will be used as a conservative estimate of
82
  /// whether a non-arrow function needs to eagerly create and capture its
83
  /// Arguments object.
84
  bool containsArrowFunctionsUsingArguments = false;
85
86
  /// Number of labels allocated so far. We use this counter to assign
87
  /// consecutive index values to labels.
88
  unsigned labelCount = 0;
89
90
  /// Indicates whether this function has been hoisted.
91
  bool hoisted{};
92
93
  /// Allocate a new label and return its index.
94
66.5k
  unsigned allocateLabel() {
95
66.5k
    return labelCount++;
96
66.5k
  }
97
};
98
99
/// Identifier and label tables, populated by the semantic validator. They need
100
/// to be stored separately from the AST because they have destructors, while
101
/// the AST is stored in a pool.
102
class SemContext {
103
 public:
104
  /// Create a new instance of \c FunctionInfo.
105
23.2k
  FunctionInfo *createFunction() {
106
23.2k
    functions_.emplace_back();
107
23.2k
    return &functions_.back();
108
23.2k
  }
109
110
 private:
111
  std::deque<FunctionInfo> functions_{};
112
};
113
114
/// Perform semantic validation of the entire AST, starting from the specified
115
/// root, which should be ProgramNode.
116
bool validateAST(Context &astContext, SemContext &semCtx, ESTree::NodePtr root);
117
118
/// Perform semantic validation of the entire AST, without preparing the AST for
119
/// compilation. This will not error on features we can parse but not compile,
120
/// transform the AST, or perform compilation specific validation.
121
bool validateASTForParser(
122
    Context &astContext,
123
    SemContext &semCtx,
124
    ESTree::NodePtr root);
125
126
/// Perform semantic validation of an individual function in the given context
127
/// \param function must be a function node
128
/// \param strict specifies parent strictness.
129
bool validateFunctionAST(
130
    Context &astContext,
131
    SemContext &semCtx,
132
    ESTree::NodePtr function,
133
    bool strict);
134
135
} // namespace sem
136
} // namespace hermes
137
138
#endif // HERMES_AST_SEMVALIDATE_H