From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Apthorp <nornagon@nornagon.net>
Date: Tue, 26 Feb 2019 17:07:45 -0800
Subject: build: add GN build files

This adds GN build files for Node, so we don't have to build with GYP.

Note that there always GN files in upstream Node in 20/21 branches,
however those files were cherry-picked from main branch and do not
really in 20/21. We have to wait until 22 is released to be able to
build with upstream GN files.

diff --git a/node.gni b/node.gni
index a2123cc6c6d21c53fafc8934203b3720393e7b11..245a43920c7baf000ba63192a84a4c3fd219be7d 100644
--- a/node.gni
+++ b/node.gni
@@ -5,10 +5,10 @@
 # Embedder options.
 declare_args() {
   # The location of Node.js in source code tree.
-  node_path = "//node"
+  node_path = "//third_party/electron_node"
 
   # The location of V8 - use the one from node's deps by default.
-  node_v8_path = "$node_path/deps/v8"
+  node_v8_path = "//v8"
 
   # The location of OpenSSL - use the one from node's deps by default.
   node_openssl_path = "$node_path/deps/openssl"
@@ -44,7 +44,7 @@ declare_args() {
   node_openssl_system_ca_path = ""
 
   # Initialize v8 platform during node.js startup.
-  node_use_v8_platform = true
+  node_use_v8_platform = false
 
   # Custom build tag.
   node_tag = ""
@@ -64,10 +64,16 @@ declare_args() {
   # TODO(zcbenz): There are few broken things for now:
   #   1. cross-os compilation is not supported.
   #   2. node_mksnapshot crashes when cross-compiling for x64 from arm64.
-  node_use_node_snapshot = (host_os == target_os) && !(host_cpu == "arm64" && target_cpu == "x64")
+  node_use_node_snapshot = false
 
   # Build with Amaro (TypeScript utils).
   node_use_amaro = true
+
+  # Allows downstream packagers (eg. Linux distributions) to build against system shared libraries.
+  use_system_cares = false
+  use_system_nghttp2 = false
+  use_system_llhttp = false
+  use_system_histogram = false
 }
 
 assert(!node_enable_inspector || node_use_openssl,
diff --git a/src/inspector/unofficial.gni b/src/inspector/unofficial.gni
index 5d87f3c901ab509e534598ed1eb0796a96355b5e..3d7aa148678b2646b88fa7c32abec91791b02b82 100644
--- a/src/inspector/unofficial.gni
+++ b/src/inspector/unofficial.gni
@@ -13,7 +13,7 @@ template("inspector_gn_build") {
   }
 
   node_gen_dir = get_label_info("../..", "target_gen_dir")
-  protocol_tool_path = "../../tools/inspector_protocol"
+  protocol_tool_path = "../../deps/inspector_protocol"
 
   gypi_values = exec_script(
       "../../tools/gypi_to_gn.py",
@@ -35,6 +35,8 @@ template("inspector_gn_build") {
     ]
 
     args = [
+      "--inspector_protocol_dir",
+      rebase_path(protocol_tool_path, root_build_dir),
       "--jinja_dir",
       # jinja is in third_party.
       rebase_path("//third_party/", root_build_dir),
@@ -72,4 +74,37 @@ template("inspector_gn_build") {
     outputs = [ "$node_gen_dir/src/{{source_name_part}}.json" ]
     args = [ "{{source}}" ] + rebase_path(outputs, root_build_dir)
   }
+
+  config("crdtp_config") {
+    include_dirs = [ protocol_tool_path ]
+  }
+
+  static_library("crdtp") {
+    public_configs = [ ":crdtp_config" ]
+    sources = [
+      "$protocol_tool_path/crdtp/cbor.cc",
+      "$protocol_tool_path/crdtp/cbor.h",
+      "$protocol_tool_path/crdtp/dispatch.cc",
+      "$protocol_tool_path/crdtp/dispatch.h",
+      "$protocol_tool_path/crdtp/error_support.cc",
+      "$protocol_tool_path/crdtp/error_support.h",
+      "$protocol_tool_path/crdtp/export.h",
+      "$protocol_tool_path/crdtp/find_by_first.h",
+      "$protocol_tool_path/crdtp/frontend_channel.h",
+      "$protocol_tool_path/crdtp/glue.h",
+      "$protocol_tool_path/crdtp/json.cc",
+      "$protocol_tool_path/crdtp/json.h",
+      "$protocol_tool_path/crdtp/parser_handler.h",
+      "$protocol_tool_path/crdtp/protocol_core.cc",
+      "$protocol_tool_path/crdtp/protocol_core.h",
+      "$protocol_tool_path/crdtp/serializable.cc",
+      "$protocol_tool_path/crdtp/serializable.h",
+      "$protocol_tool_path/crdtp/span.cc",
+      "$protocol_tool_path/crdtp/span.h",
+      "$protocol_tool_path/crdtp/status.cc",
+      "$protocol_tool_path/crdtp/status.h",
+      "$protocol_tool_path/crdtp/json_platform.cc",
+      "$protocol_tool_path/crdtp/json_platform.h",
+    ]
+  }
 }
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
index 894fd515202cc3a1f933c2bbc618dd09869ad904..4f1ed661e9c432f3b50f2e7e348ad9794ff773d0 100644
--- a/src/node_builtins.cc
+++ b/src/node_builtins.cc
@@ -781,6 +781,7 @@ void BuiltinLoader::RegisterExternalReferences(
   registry->Register(GetNatives);
 
   RegisterExternalReferencesForInternalizedBuiltinCode(registry);
+  EmbedderRegisterExternalReferencesForInternalizedBuiltinCode(registry);
 }
 
 }  // namespace builtins
diff --git a/src/node_builtins.h b/src/node_builtins.h
index a73de23a1debfdac66873e0baccf882e383bfc36..7ac5291be093773ee7efd39e77e01bf5d5ce5247 100644
--- a/src/node_builtins.h
+++ b/src/node_builtins.h
@@ -74,6 +74,8 @@ using BuiltinCodeCacheMap =
 // Generated by tools/js2c.cc as node_javascript.cc
 void RegisterExternalReferencesForInternalizedBuiltinCode(
     ExternalReferenceRegistry* registry);
+void EmbedderRegisterExternalReferencesForInternalizedBuiltinCode(
+    ExternalReferenceRegistry* registry);
 
 // Handles compilation and caching of built-in JavaScript modules and
 // bootstrap scripts, whose source are bundled into the binary as static data.
diff --git a/tools/install.py b/tools/install.py
index 17515720ba9c85d533465365188021074a8d30f4..7232be863d517c8445059a57c5938c2cbdeaf81b 100755
--- a/tools/install.py
+++ b/tools/install.py
@@ -291,6 +291,7 @@ def headers(options, action):
       'include/v8-promise.h',
       'include/v8-proxy.h',
       'include/v8-regexp.h',
+      'include/v8-sandbox.h',
       'include/v8-script.h',
       'include/v8-snapshot.h',
       'include/v8-source-location.h',
diff --git a/tools/js2c.cc b/tools/js2c.cc
old mode 100644
new mode 100755
index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0
--- a/tools/js2c.cc
+++ b/tools/js2c.cc
@@ -28,6 +28,7 @@ namespace js2c {
 int Main(int argc, char* argv[]);
 
 static bool is_verbose = false;
+static bool only_js = false;
 
 void Debug(const char* format, ...) {
   va_list arguments;
@@ -175,6 +176,7 @@ const char* kTemplate = R"(
 #include "node_builtins.h"
 #include "node_external_reference.h"
 #include "node_internals.h"
+#include "node_threadsafe_cow-inl.h"
 
 namespace node {
 
@@ -190,7 +192,11 @@ const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
 }  // anonymous namespace
 
 void BuiltinLoader::LoadJavaScriptSource() {
-  source_ = global_source_map;
+  BuiltinSourceMap map = *source_.read();
+  BuiltinSourceMap new_map = *global_source_map.read();
+
+  map.merge(new_map);
+  source_ = ThreadsafeCopyOnWrite<BuiltinSourceMap>(map);
 }
 
 void RegisterExternalReferencesForInternalizedBuiltinCode(
@@ -207,6 +213,45 @@ UnionBytes BuiltinLoader::GetConfig() {
 }  // namespace node
 )";
 
+const char* kEmbedderTemplate = R"(
+#include "env-inl.h"
+#include "node_builtins.h"
+#include "node_external_reference.h"
+#include "node_internals.h"
+#include "node_threadsafe_cow-inl.h"
+
+namespace node {
+
+namespace builtins {
+
+%.*s
+namespace {
+const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
+  BuiltinSourceMap {
+%.*s
+  }  // BuiltinSourceMap
+
+};  // ThreadsafeCopyOnWrite
+}  // anonymous namespace
+
+void BuiltinLoader::LoadEmbedderJavaScriptSource() {
+  BuiltinSourceMap map = *source_.read();
+  BuiltinSourceMap new_map = *global_source_map.read();
+
+  map.merge(new_map);
+  source_ = ThreadsafeCopyOnWrite<BuiltinSourceMap>(map);
+}
+
+void EmbedderRegisterExternalReferencesForInternalizedBuiltinCode(
+  ExternalReferenceRegistry* registry) {
+%.*s
+}
+
+}  // namespace builtins
+
+}  // namespace node
+)";
+
 Fragment Format(const Fragments& definitions,
                 const Fragments& initializers,
                 const Fragments& registrations) {
@@ -216,13 +261,12 @@ Fragment Format(const Fragments& definitions,
   size_t init_size = init_buf.size();
   std::vector<char> reg_buf = Join(registrations, "\n");
   size_t reg_size = reg_buf.size();
-
-  size_t result_size =
-      def_size + init_size + reg_size + strlen(kTemplate) + 100;
+  size_t result_size = def_size + init_size + reg_size +
+          strlen(only_js ? kEmbedderTemplate: kTemplate) + 300;
   std::vector<char> result(result_size, 0);
   int r = snprintf(result.data(),
                    result_size,
-                   kTemplate,
+                   only_js ? kEmbedderTemplate: kTemplate,
                    static_cast<int>(def_buf.size()),
                    def_buf.data(),
                    static_cast<int>(init_buf.size()),
@@ -846,12 +890,15 @@ int JS2C(const FileList& js_files,
     }
   }
 
+  if (!only_js) {
   assert(FilenameIsConfigGypi(config));
   // "config.gypi" -> config_raw.
   int r = AddGypi("config", config, &definitions);
   if (r != 0) {
     return r;
   }
+  }
+
   Fragment out = Format(definitions, initializers, registrations);
   return WriteIfChanged(out, dest);
 }
@@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) {
     std::string arg(argv[i]);
     if (arg == "--verbose") {
       is_verbose = true;
+    } else if (arg == "--only-js") {
+      only_js = true;
     } else if (arg == "--root") {
       if (i == argc - 1) {
         fprintf(stderr, "--root must be followed by a path\n");
@@ -925,6 +974,14 @@ int Main(int argc, char* argv[]) {
     }
   }
 
+  if (only_js) {
+    auto js_it = file_map.find(".js");
+
+    assert(file_map.size() == 1);
+    assert(js_it != file_map.end());
+
+    return JS2C(js_it->second, FileList(), std::string(), output);
+  } else {
   // Should have exactly 3 types: `.js`, `.mjs` and `.gypi`.
   assert(file_map.size() == 3);
   auto gypi_it = file_map.find(".gypi");
@@ -951,6 +1008,7 @@ int Main(int argc, char* argv[]) {
   std::sort(mjs_it->second.begin(), mjs_it->second.end());
 
   return JS2C(js_it->second, mjs_it->second, gypi_it->second[0], output);
+  }
 }
 }  // namespace js2c
 }  // namespace node
diff --git a/tools/search_files.py b/tools/search_files.py
index 65d0e1be42f0a85418491ebb548278cf431aa6a0..d4a31342f1c6107b029394c6e1d00a1d1e877e03 100755
--- a/tools/search_files.py
+++ b/tools/search_files.py
@@ -14,6 +14,7 @@ if __name__ == '__main__':
   try:
     files = SearchFiles(*sys.argv[2:])
     files = [ os.path.relpath(x, sys.argv[1]) for x in files ]
+    files = [os.path.normpath(x).replace(os.sep, '/') for x in files]
     print('\n'.join(files))
   except Exception as e:
     print(str(e))
diff --git a/unofficial.gni b/unofficial.gni
index 9e496d99d7141bf42ef7374a3c676c7b333eeeab..a2f3a769ceaa08db6d7438223884dc5aeab1340d 100644
--- a/unofficial.gni
+++ b/unofficial.gni
@@ -145,6 +145,7 @@ template("node_gn_build") {
     public_deps = [
       "deps/ada",
       "deps/uv",
+      "//electron:electron_js2c",
       "deps/simdjson",
       "$node_v8_path",
     ]
@@ -156,7 +157,6 @@ template("node_gn_build") {
       "deps/llhttp",
       "deps/nbytes",
       "deps/nghttp2",
-      "deps/ngtcp2",
       "deps/postject",
       "deps/sqlite",
       "deps/uvwasi",
@@ -165,7 +165,11 @@ template("node_gn_build") {
       "$node_v8_path:v8_libplatform",
     ]
 
+    cflags_cc = [ "-Wno-unguarded-availability-new" ]
+
     sources = [
+      "src/node_snapshot_stub.cc",
+      "$root_gen_dir/electron_natives.cc",
       "$target_gen_dir/node_javascript.cc",
     ] + gypi_values.node_sources
 
@@ -185,11 +189,12 @@ template("node_gn_build") {
     }
     if (node_use_openssl) {
       deps += [ "deps/ncrypto" ]
-      public_deps += [ "$node_openssl_path" ]
+      public_deps += [ "//third_party/boringssl" ]
       sources += gypi_values.node_crypto_sources
     }
     if (node_enable_inspector) {
       deps += [
+        "src/inspector:crdtp",
         "src/inspector:node_protocol_generated_sources",
         "src/inspector:v8_inspector_compress_protocol_json",
       ]
@@ -282,6 +287,7 @@ template("node_gn_build") {
   }
 
   executable("node_js2c") {
+    defines = []
     deps = [
       "deps/uv",
       "$node_simdutf_path",
@@ -292,26 +298,75 @@ template("node_gn_build") {
       "src/embedded_data.cc",
       "src/embedded_data.h",
     ]
-    include_dirs = [ "src" ]
+    include_dirs = [ "src", "tools" ]
+
+    if (!is_win) {
+      defines += [ "NODE_JS2C_USE_STRING_LITERALS" ]
+    }
+  }
+
+  node_deps_files = gypi_values.deps_files + node_builtin_shareable_builtins
+  node_library_files = exec_script("./tools/search_files.py",
+                                    [ rebase_path(".", root_build_dir),
+                                      rebase_path("lib", root_build_dir),
+                                      "js" ],
+                                    "list lines")
+
+  fs_files = [
+    "lib/internal/fs/cp/cp-sync.js",
+    "lib/internal/fs/cp/cp.js",
+    "lib/internal/fs/dir.js",
+    "lib/internal/fs/glob.js",
+    "lib/internal/fs/promises.js",
+    "lib/internal/fs/read/context.js",
+    "lib/internal/fs/recursive_watch.js",
+    "lib/internal/fs/rimraf.js",
+    "lib/internal/fs/streams.js",
+    "lib/internal/fs/sync_write_stream.js",
+    "lib/internal/fs/utils.js",
+    "lib/internal/fs/watchers.js",
+    "lib/fs.js",
+    "lib/fs/promises.js"
+  ]
+
+  original_fs_files = []
+  foreach(file, fs_files) {
+    original_fs_files += [string_replace(string_replace(string_replace(file, "internal/fs/", "internal/original-fs/"), "lib/fs.js", "lib/original-fs.js"), "lib/fs/", "lib/original-fs/")]
+  }
+
+  copy("node_js2c_inputs") {
+    sources = node_deps_files + node_library_files
+    outputs = [
+      "$target_gen_dir/js2c_inputs/{{source_target_relative}}",
+    ]
+  }
+
+  action("node_js2c_original_fs") {
+    script = "//electron/script/node/generate_original_fs.py"
+    inputs = fs_files
+    deps = [ ":node_js2c_inputs" ]
+
+    outputs = []
+    foreach(file, original_fs_files) {
+      outputs += ["$target_gen_dir/js2c_inputs/$file"]
+    }
+
+    args = [rebase_path("$target_gen_dir/js2c_inputs")] + fs_files
   }
 
   action("run_node_js2c") {
-    script = "$node_v8_path/tools/run.py"
+    script = "//electron/build/run-in-dir.py"
     deps = [
+      ":node_js2c_original_fs",
       ":node_js2c($host_toolchain)",
       ":generate_config_gypi",
     ]
 
-    node_deps_files = gypi_values.deps_files + node_builtin_shareable_builtins
-    node_library_files = exec_script("./tools/search_files.py",
-                                     [ rebase_path(".", root_build_dir),
-                                       rebase_path("lib", root_build_dir),
-                                       "js" ],
-                                     "list lines")
-
+    config_gypi = [ "$target_gen_dir/config.gypi" ]
     inputs = node_library_files +
              node_deps_files +
-             [ "$target_gen_dir/config.gypi" ]
+             get_target_outputs(":node_js2c_original_fs") +
+             config_gypi
     outputs = [ "$target_gen_dir/node_javascript.cc" ]
 
     # Get the path to node_js2c executable of the host toolchain.
@@ -325,11 +380,11 @@ template("node_gn_build") {
         get_label_info(":node_js2c($host_toolchain)", "name") +
         host_executable_suffix
 
-    args = [ rebase_path(node_js2c_path),
-             rebase_path("$target_gen_dir/node_javascript.cc"),
-             "--root", rebase_path("."),
-             "lib", rebase_path("$target_gen_dir/config.gypi") ] +
-           node_deps_files
+    args = [ rebase_path("$target_gen_dir/js2c_inputs"),
+             rebase_path(node_js2c_path),
+             rebase_path("$target_gen_dir/node_javascript.cc")] +
+             rebase_path(config_gypi) + node_deps_files +
+             original_fs_files + node_library_files
   }
 
   executable("node_cctest") {
