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/configure.py b/configure.py
index 2415940835036226799a7ea14c6687cc0d56c523..0feb07afbccad97a92cee00954443407eb20ac67 100755
--- a/configure.py
+++ b/configure.py
@@ -1722,7 +1722,7 @@ def configure_v8(o, configs):
   # Until we manage to get rid of all those, v8_enable_sandbox cannot be used.
   # Note that enabling pointer compression without enabling sandbox is unsupported by V8,
   # so this can be broken at any time.
-  o['variables']['v8_enable_sandbox'] = 0
+  o['variables']['v8_enable_sandbox'] = 1 if options.enable_pointer_compression else 0
   o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.enable_pointer_compression else 0
   o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0
   o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0
diff --git a/node.gni b/node.gni
index d4438f7fd61598afac2c1e3184721a759d22b10c..e2407027ab05e59b2f0f1c213b98ea469db7a91b 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"
@@ -50,7 +50,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 = ""
@@ -70,10 +70,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/node_builtins.cc b/src/node_builtins.cc
index b4acc40618e372b09d0cb5e3755034f08711a282..efeaaef7e4dc64a0adb5e6bdbbe18945890de62c 100644
--- a/src/node_builtins.cc
+++ b/src/node_builtins.cc
@@ -789,6 +789,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 f9426599f2d5dc6ad061407f0c4eb2c9203a4433..302030f610965f07dd6998d282275c1bdf738009 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 8797b59e59c85a8877b977fa3281e50165e6f6b2..0af01e075616195f38fb242626dcab770ec1eb57 100755
--- a/tools/install.py
+++ b/tools/install.py
@@ -222,6 +222,7 @@ def headers(options, action):
       'include/cppgc/internal/caged-heap-local-data.h',
       'include/cppgc/internal/caged-heap.h',
       'include/cppgc/internal/compiler-specific.h',
+      'include/cppgc/internal/conditional-stack-allocated.h',
       'include/cppgc/internal/finalizer-trait.h',
       'include/cppgc/internal/gc-info.h',
       'include/cppgc/internal/logging.h',
@@ -301,6 +302,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 856878c33681a73d41016729dabe48b0a6a80589..91a11852d206b65485fe90fd037a0bd17a16c20b 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]
     # Apply the same transform in SearchFiles after relpath
     if sys.platform == 'win32':
       files = [ x.replace('\\', '/') for x in files ]
diff --git a/unofficial.gni b/unofficial.gni
index 865a0d5ce9c6792e57f4216bcaa594ca6fc7b1c8..26ebc811272ef2990f8d090c54e7f5294aab9d37 100644
--- a/unofficial.gni
+++ b/unofficial.gni
@@ -147,31 +147,41 @@ template("node_gn_build") {
     public_configs = [
       ":node_external_config",
       "deps/googletest:googletest_config",
+      ":zstd_include_config"
     ]
     public_deps = [
       "deps/ada",
       "deps/uv",
+      "//electron:electron_js2c",
       "deps/simdjson",
       "$node_v8_path",
     ]
     deps = [
       ":run_node_js2c",
-      "deps/brotli",
       "deps/cares",
       "deps/histogram",
       "deps/llhttp",
       "deps/nbytes",
       "deps/nghttp2",
-      "deps/ngtcp2",
       "deps/postject",
       "deps/uvwasi",
-      "deps/zstd",
       "//third_party/zlib",
+      "//third_party/brotli:dec",
+      "//third_party/brotli:enc",
+      "//third_party/zstd:decompress",
+      "//third_party/zstd:headers",
       "$node_simdutf_path",
       "$node_v8_path:v8_libplatform",
     ]
 
+    cflags_cc = [
+      "-Wno-unguarded-availability-new",
+      "-Wno-return-stack-address"
+    ]
+
     sources = [
+      "src/node_snapshot_stub.cc",
+      "$root_gen_dir/electron_natives.cc",
       "$target_gen_dir/node_javascript.cc",
     ] + gypi_values.node_sources
 
@@ -194,7 +204,7 @@ 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_use_sqlite) {
@@ -223,6 +233,10 @@ template("node_gn_build") {
     }
   }
 
+  config("zstd_include_config") {
+    include_dirs = [ "//third_party/zstd/src/lib" ]
+  }
+
   executable(target_name) {
     forward_variables_from(invoker, "*")
 
@@ -297,6 +311,7 @@ template("node_gn_build") {
   }
 
   executable("node_js2c") {
+    defines = []
     deps = [
       "deps/uv",
       "$node_simdutf_path",
@@ -307,26 +322,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.
@@ -340,11 +404,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") {
