summaryrefslogtreecommitdiff
path: root/src/node_builtins.h
blob: 2dd3ee8b8c9c4e5eecdf5705b087343993e76cd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#ifndef SRC_NODE_BUILTINS_H_
#define SRC_NODE_BUILTINS_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <list>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "node_external_reference.h"
#include "node_mutex.h"
#include "node_threadsafe_cow.h"
#include "node_union_bytes.h"
#include "v8.h"

// Forward declare test fixture for `friend` declaration.
class PerProcessTest;

namespace node {
class SnapshotBuilder;
class ExternalReferenceRegistry;
class Realm;

namespace builtins {

using BuiltinSourceMap = std::map<std::string, UnionBytes>;
using BuiltinCodeCacheMap =
    std::unordered_map<std::string,
                       std::unique_ptr<v8::ScriptCompiler::CachedData>>;

// Generated by tools/js2c.py as node_javascript.cc
void RegisterExternalReferencesForInternalizedBuiltinCode(
    ExternalReferenceRegistry* registry);

struct CodeCacheInfo {
  std::string id;
  std::vector<uint8_t> data;
};

// Handles compilation and caching of built-in JavaScript modules and
// bootstrap scripts, whose source are bundled into the binary as static data.
class NODE_EXTERN_PRIVATE BuiltinLoader {
 public:
  BuiltinLoader();
  BuiltinLoader(const BuiltinLoader&) = delete;
  BuiltinLoader& operator=(const BuiltinLoader&) = delete;

  static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
  static void CreatePerIsolateProperties(
      IsolateData* isolate_data, v8::Local<v8::FunctionTemplate> target);
  static void CreatePerContextProperties(v8::Local<v8::Object> target,
                                         v8::Local<v8::Value> unused,
                                         v8::Local<v8::Context> context,
                                         void* priv);

  // The parameters used to compile the scripts are detected based on
  // the pattern of the id.
  v8::MaybeLocal<v8::Function> LookupAndCompile(v8::Local<v8::Context> context,
                                                const char* id,
                                                Realm* optional_realm);

  v8::MaybeLocal<v8::Value> CompileAndCall(v8::Local<v8::Context> context,
                                           const char* id,
                                           int argc,
                                           v8::Local<v8::Value> argv[],
                                           Realm* optional_realm);

  v8::MaybeLocal<v8::Value> CompileAndCall(v8::Local<v8::Context> context,
                                           const char* id,
                                           Realm* realm);

  v8::Local<v8::Object> GetSourceObject(v8::Local<v8::Context> context);
  // Returns config.gypi as a JSON string
  v8::Local<v8::String> GetConfigString(v8::Isolate* isolate);
  bool Exists(const char* id);
  bool Add(const char* id, const UnionBytes& source);

  bool CompileAllBuiltins(v8::Local<v8::Context> context);
  void RefreshCodeCache(const std::vector<CodeCacheInfo>& in);
  void CopyCodeCache(std::vector<CodeCacheInfo>* out) const;

  void CopySourceAndCodeCacheReferenceFrom(const BuiltinLoader* other);

 private:
  // Only allow access from friends.
  friend class CodeCacheBuilder;

  // Generated by tools/js2c.py as node_javascript.cc
  void LoadJavaScriptSource();  // Loads data into source_
  UnionBytes GetConfig();       // Return data for config.gypi

  std::vector<std::string> GetBuiltinIds() const;

  struct BuiltinCategories {
    std::set<std::string> can_be_required;
    std::set<std::string> cannot_be_required;
  };
  // This method builds `BuiltinCategories` from scratch every time,
  // and is therefore somewhat expensive, but also currently only being
  // used for testing, so that should not be an issue.
  BuiltinCategories GetBuiltinCategories() const;

  const v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const;
  enum class Result { kWithCache, kWithoutCache };
  v8::MaybeLocal<v8::String> LoadBuiltinSource(v8::Isolate* isolate,
                                               const char* id) const;
  // If an exception is encountered (e.g. source code contains
  // syntax error), the returned value is empty.
  v8::MaybeLocal<v8::Function> LookupAndCompileInternal(
      v8::Local<v8::Context> context,
      const char* id,
      std::vector<v8::Local<v8::String>>* parameters,
      Result* result);

  static void RecordResult(const char* id,
                           BuiltinLoader::Result result,
                           Realm* realm);
  static void GetBuiltinCategories(
      v8::Local<v8::Name> property,
      const v8::PropertyCallbackInfo<v8::Value>& info);
  static void GetCacheUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
  // Passing ids of built-in source code into JS land as
  // internalBinding('builtins').builtinIds
  static void BuiltinIdsGetter(v8::Local<v8::Name> property,
                               const v8::PropertyCallbackInfo<v8::Value>& info);
  // Passing config.gypi into JS land as internalBinding('builtins').config
  static void ConfigStringGetter(
      v8::Local<v8::Name> property,
      const v8::PropertyCallbackInfo<v8::Value>& info);
  // Compile a specific built-in as a function
  static void CompileFunction(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void HasCachedBuiltins(
      const v8::FunctionCallbackInfo<v8::Value>& args);

  void AddExternalizedBuiltin(const char* id, const char* filename);

  ThreadsafeCopyOnWrite<BuiltinSourceMap> source_;

  const UnionBytes config_;

  struct BuiltinCodeCache {
    RwLock mutex;
    BuiltinCodeCacheMap map;
    bool has_code_cache = false;
  };
  std::shared_ptr<BuiltinCodeCache> code_cache_;

  friend class ::PerProcessTest;
};
}  // namespace builtins

}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_BUILTINS_H_