From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Thu, 11 Apr 2019 17:16:13 +0900
Subject: build: modify js2c.py to allow injection of original-fs and custom
 embedder JS

This patch does two things:
* Updates js2c.py so that original-fs is automatically created with
support for streams by copying the file at build time and making a new
builtin called "original-fs" and "original-fs/streams"
* Updates js2c.py so that //electron can call it as part of its build
process and provide embedder modules (electrons
renderer/browser/worker/sandboxed bootstrap scripts).  These are loaded
through LoadEmbedderJavaScriptSource()

diff --git a/lib/internal/fs/watchers.js b/lib/internal/fs/watchers.js
index bc4555584ab1f97806a1e9cd17085a2488320908..b17dbf2a98c9f4b14fea60c87f05afcee6ec54fb 100644
--- a/lib/internal/fs/watchers.js
+++ b/lib/internal/fs/watchers.js
@@ -293,11 +293,13 @@ function emitCloseNT(self) {
 
 // Legacy alias on the C++ wrapper object. This is not public API, so we may
 // want to runtime-deprecate it at some point. There's no hurry, though.
-ObjectDefineProperty(FSEvent.prototype, 'owner', {
-  __proto__: null,
-  get() { return this[owner_symbol]; },
-  set(v) { return this[owner_symbol] = v; }
-});
+if (!'owner' in FSEvent.prototype) {
+  ObjectDefineProperty(FSEvent.prototype, 'owner', {
+ __proto__: null,
+    get() { return this[owner_symbol]; },
+    set(v) { return this[owner_symbol] = v; }
+  });
+}
 
 async function* watch(filename, options = kEmptyObject) {
   const path = toNamespacedPath(getValidatedPath(filename));
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
index 40d9025746d3c39cf9ea27b6cffc8f2eb7e62c1e..d3a0dd7cedb0d239ae427d1af2335e155345a454 100644
--- a/src/node_builtins.cc
+++ b/src/node_builtins.cc
@@ -33,6 +33,7 @@ BuiltinLoader BuiltinLoader::instance_;
 
 BuiltinLoader::BuiltinLoader() : config_(GetConfig()), has_code_cache_(false) {
   LoadJavaScriptSource();
+  LoadEmbedderJavaScriptSource();
 #ifdef NODE_SHARED_BUILTIN_CJS_MODULE_LEXER_LEXER_PATH
   AddExternalizedBuiltin(
       "internal/deps/cjs-module-lexer/lexer",
diff --git a/src/node_builtins.h b/src/node_builtins.h
index 90b158b84bb2a66781cf92f5b4c1a64f9e2ee651..8d9f7c409659a30747e5feeac6cfec4208791370 100644
--- a/src/node_builtins.h
+++ b/src/node_builtins.h
@@ -71,6 +71,7 @@ class NODE_EXTERN_PRIVATE BuiltinLoader {
 
   // Generated by tools/js2c.py as node_javascript.cc
   void LoadJavaScriptSource();  // Loads data into source_
+  void LoadEmbedderJavaScriptSource();  // Loads embedder data into source_
   UnionBytes GetConfig();       // Return data for config.gypi
 
   std::vector<std::string> GetBuiltinIds();
diff --git a/tools/js2c.py b/tools/js2c.py
index 8ba46c5d78c5c86d9f7b8b6972f3febbe87de61e..38057495e04eba46ca87f6a0ea607f0fff46846e 100755
--- a/tools/js2c.py
+++ b/tools/js2c.py
@@ -39,6 +39,8 @@ import codecs
 import utils
 
 def ReadFile(filename):
+  if filename.startswith("//v8"):
+    filename = "../../" + filename[2:]
   if is_verbose:
     print(filename)
   with codecs.open(filename, "r", "utf-8") as f:
@@ -57,13 +59,15 @@ namespace builtins {{
 
 {0}
 
-void BuiltinLoader::LoadJavaScriptSource() {{
+void BuiltinLoader::Load{4}JavaScriptSource() {{
   {1}
 }}
 
+#if {2}
 UnionBytes BuiltinLoader::GetConfig() {{
-  return UnionBytes(config_raw, {2});  // config.gypi
+  return UnionBytes(config_raw, {3});  // config.gypi
 }}
+#endif
 
 }}  // namespace builtins
 
@@ -113,8 +117,8 @@ def GetDefinition(var, source, step=30):
   return definition, len(code_points)
 
 
-def AddModule(filename, definitions, initializers):
-  code = ReadFile(filename)
+def AddModule(filename, definitions, initializers, ReadFileFn=ReadFile):
+  code = ReadFileFn(filename)
   name = NormalizeFileName(filename)
   slug = SLUGGER_RE.sub('_', name)
   var = slug + '_raw'
@@ -124,7 +128,9 @@ def AddModule(filename, definitions, initializers):
   initializers.append(initializer)
 
 def NormalizeFileName(filename):
-  split = filename.split('/')
+  if filename.startswith('//v8'):
+    filename = "deps/" + filename[2:]
+  split = os.path.normpath(filename).split(os.path.sep)
   if split[0] == 'deps':
     split = ['internal'] + split
   else:  # `lib/**/*.js` so drop the 'lib' part
@@ -142,23 +148,36 @@ def NormalizeFileName(filename):
   return os.path.splitext(filename)[0]
 
 
-def JS2C(source_files, target):
+def JS2C(source_files, target, only_js):
   # Build source code lines
   definitions = []
   initializers = []
 
-  for filename in source_files['.js']:
-    AddModule(filename, definitions, initializers)
-  for filename in source_files['.mjs']:
-    AddModule(filename, definitions, initializers)
-
-  config_def, config_size = handle_config_gypi(source_files['config.gypi'])
-  definitions.append(config_def)
+  for extension in source_files.keys():
+    if extension == '.js' or extension == '.mjs':
+      for filename in source_files[extension]:
+        AddModule(filename, definitions, initializers)
+
+        # Electron: Expose fs module without asar support.
+        if filename == 'lib/fs.js':
+          # Node's 'fs' and 'internal/fs/<filename> have lazy-loaded circular
+          # dependencies. So to expose the unmodified Node 'fs' functionality here,
+          # we have to copy both 'fs' *and* 'internal/fs/<filename>' files and modify the
+          # copies to depend on each other instead of on our asarified 'fs' code.
+          AddModule('lib/original-fs.js', definitions, initializers, lambda _: ReadFile(filename).replace("require('internal/fs/", "require('internal/original-fs/"))
+        elif filename.startswith('lib/internal/fs/'):
+          original_fs_filename = filename.replace('internal/fs/', 'internal/original-fs/')
+          AddModule(original_fs_filename, definitions, initializers, lambda _: ReadFile(filename).replace("require('fs')", "require('original-fs')"))
+
+  config_size = 0
+  if not only_js:
+    config_def, config_size = handle_config_gypi(source_files['config.gypi'])
+    definitions.append(config_def)
 
   # Emit result
   definitions = ''.join(definitions)
   initializers = '\n  '.join(initializers)
-  out = TEMPLATE.format(definitions, initializers, config_size)
+  out = TEMPLATE.format(definitions, initializers, '0' if only_js else '1', config_size, 'Embedder' if only_js else '')
   write_if_chaged(out, target)
 
 
@@ -218,6 +237,7 @@ def main():
       default=None,
       help='input file directory')
   parser.add_argument('--verbose', action='store_true', help='output file')
+  parser.add_argument('--only-js', action='store_true', help='do not require or parse any config.gypi files')
   parser.add_argument('sources', nargs='*', help='input files')
   options = parser.parse_args()
   global is_verbose
@@ -230,12 +250,15 @@ def main():
 
   source_files = functools.reduce(SourceFileByExt, sources, {})
 
-  # Should have exactly 3 types: `.js`, `.mjs` and `.gypi`
-  assert len(source_files) == 3
-  # Currently config.gypi is the only `.gypi` file allowed
-  assert source_files['.gypi'] == ['config.gypi']
-  source_files['config.gypi'] = source_files.pop('.gypi')[0]
-  JS2C(source_files, options.target)
+  if options.only_js:
+    assert len(source_files) == 1
+  else:
+    # Should have exactly 3 types: `.js`, `.mjs` and `.gypi`
+    assert len(source_files) == 3
+    # Currently config.gypi is the only `.gypi` file allowed
+    assert source_files['.gypi'][0].endswith('config.gypi')
+    source_files['config.gypi'] = source_files.pop('.gypi')[0]
+  JS2C(source_files, options.target, options.only_js)
 
 
 if __name__ == "__main__":
