chore: remove node patches by using the preload feature (#41080)
This commit is contained in:
		
					parent
					
						
							
								031d636823
							
						
					
				
			
			
				commit
				
					
						d13a93fb61
					
				
			
		
					 21 changed files with 403 additions and 135 deletions
				
			
		
							
								
								
									
										22
									
								
								BUILD.gn
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								BUILD.gn
									
										
									
									
									
								
							|  | @ -166,15 +166,6 @@ npm_action("build_electron_definitions") { | ||||||
|   outputs = [ "$target_gen_dir/tsc/typings/electron.d.ts" ] |   outputs = [ "$target_gen_dir/tsc/typings/electron.d.ts" ] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| webpack_build("electron_asar_bundle") { |  | ||||||
|   deps = [ ":build_electron_definitions" ] |  | ||||||
| 
 |  | ||||||
|   inputs = auto_filenames.asar_bundle_deps |  | ||||||
| 
 |  | ||||||
|   config_file = "//electron/build/webpack/webpack.config.asar.js" |  | ||||||
|   out_file = "$target_gen_dir/js2c/asar_bundle.js" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| webpack_build("electron_browser_bundle") { | webpack_build("electron_browser_bundle") { | ||||||
|   deps = [ ":build_electron_definitions" ] |   deps = [ ":build_electron_definitions" ] | ||||||
| 
 | 
 | ||||||
|  | @ -220,6 +211,15 @@ webpack_build("electron_isolated_renderer_bundle") { | ||||||
|   out_file = "$target_gen_dir/js2c/isolated_bundle.js" |   out_file = "$target_gen_dir/js2c/isolated_bundle.js" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | webpack_build("electron_node_bundle") { | ||||||
|  |   deps = [ ":build_electron_definitions" ] | ||||||
|  | 
 | ||||||
|  |   inputs = auto_filenames.node_bundle_deps | ||||||
|  | 
 | ||||||
|  |   config_file = "//electron/build/webpack/webpack.config.node.js" | ||||||
|  |   out_file = "$target_gen_dir/js2c/node_init.js" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| webpack_build("electron_utility_bundle") { | webpack_build("electron_utility_bundle") { | ||||||
|   deps = [ ":build_electron_definitions" ] |   deps = [ ":build_electron_definitions" ] | ||||||
| 
 | 
 | ||||||
|  | @ -231,9 +231,9 @@ webpack_build("electron_utility_bundle") { | ||||||
| 
 | 
 | ||||||
| action("electron_js2c") { | action("electron_js2c") { | ||||||
|   deps = [ |   deps = [ | ||||||
|     ":electron_asar_bundle", |  | ||||||
|     ":electron_browser_bundle", |     ":electron_browser_bundle", | ||||||
|     ":electron_isolated_renderer_bundle", |     ":electron_isolated_renderer_bundle", | ||||||
|  |     ":electron_node_bundle", | ||||||
|     ":electron_renderer_bundle", |     ":electron_renderer_bundle", | ||||||
|     ":electron_sandboxed_renderer_bundle", |     ":electron_sandboxed_renderer_bundle", | ||||||
|     ":electron_utility_bundle", |     ":electron_utility_bundle", | ||||||
|  | @ -242,9 +242,9 @@ action("electron_js2c") { | ||||||
|   ] |   ] | ||||||
| 
 | 
 | ||||||
|   sources = [ |   sources = [ | ||||||
|     "$target_gen_dir/js2c/asar_bundle.js", |  | ||||||
|     "$target_gen_dir/js2c/browser_init.js", |     "$target_gen_dir/js2c/browser_init.js", | ||||||
|     "$target_gen_dir/js2c/isolated_bundle.js", |     "$target_gen_dir/js2c/isolated_bundle.js", | ||||||
|  |     "$target_gen_dir/js2c/node_init.js", | ||||||
|     "$target_gen_dir/js2c/renderer_init.js", |     "$target_gen_dir/js2c/renderer_init.js", | ||||||
|     "$target_gen_dir/js2c/sandbox_bundle.js", |     "$target_gen_dir/js2c/sandbox_bundle.js", | ||||||
|     "$target_gen_dir/js2c/utility_init.js", |     "$target_gen_dir/js2c/utility_init.js", | ||||||
|  |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| module.exports = require('./webpack.config.base')({ |  | ||||||
|   target: 'asar', |  | ||||||
|   alwaysHasNode: true, |  | ||||||
|   targetDeletesNodeGlobals: true |  | ||||||
| }); |  | ||||||
							
								
								
									
										4
									
								
								build/webpack/webpack.config.node.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								build/webpack/webpack.config.node.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | module.exports = require('./webpack.config.base')({ | ||||||
|  |   target: 'node', | ||||||
|  |   alwaysHasNode: true | ||||||
|  | }); | ||||||
|  | @ -336,10 +336,9 @@ auto_filenames = { | ||||||
|     "typings/internal-electron.d.ts", |     "typings/internal-electron.d.ts", | ||||||
|   ] |   ] | ||||||
| 
 | 
 | ||||||
|   asar_bundle_deps = [ |   node_bundle_deps = [ | ||||||
|     "lib/asar/fs-wrapper.ts", |     "lib/node/asar-fs-wrapper.ts", | ||||||
|     "lib/asar/init.ts", |     "lib/node/init.ts", | ||||||
|     "lib/common/webpack-provider.ts", |  | ||||||
|     "package.json", |     "package.json", | ||||||
|     "tsconfig.electron.json", |     "tsconfig.electron.json", | ||||||
|     "tsconfig.json", |     "tsconfig.json", | ||||||
|  |  | ||||||
|  | @ -1,3 +0,0 @@ | ||||||
| import { wrapFsWithAsar } from './fs-wrapper'; |  | ||||||
| 
 |  | ||||||
| wrapFsWithAsar(require('fs')); |  | ||||||
							
								
								
									
										31
									
								
								lib/node/init.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/node/init.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | // Initialize ASAR support in fs module.
 | ||||||
|  | import { wrapFsWithAsar } from './asar-fs-wrapper'; | ||||||
|  | wrapFsWithAsar(require('fs')); | ||||||
|  | 
 | ||||||
|  | // Hook child_process.fork.
 | ||||||
|  | const cp = require('child_process'); | ||||||
|  | const originalFork = cp.fork; | ||||||
|  | cp.fork = (modulePath: string, args: any, options: any) => { | ||||||
|  |   // Parse optional args.
 | ||||||
|  |   if (args == null) { | ||||||
|  |     args = []; | ||||||
|  |   } else if (typeof args === 'object' && !Array.isArray(args)) { | ||||||
|  |     options = args; | ||||||
|  |     args = []; | ||||||
|  |   } | ||||||
|  |   // Fallback to original fork to report arg type errors.
 | ||||||
|  |   if (typeof modulePath !== 'string' || !Array.isArray(args) || | ||||||
|  |       (typeof options !== 'object' && typeof options !== 'undefined')) { | ||||||
|  |     return originalFork(modulePath, args, options); | ||||||
|  |   } | ||||||
|  |   // When forking a child script, we setup a special environment to make
 | ||||||
|  |   // the electron binary run like upstream Node.js.
 | ||||||
|  |   options = options ?? {}; | ||||||
|  |   options.env = Object.create(options.env || process.env); | ||||||
|  |   options.env.ELECTRON_RUN_AS_NODE = 1; | ||||||
|  |   // On mac the child script runs in helper executable.
 | ||||||
|  |   if (!options.execPath && process.platform === 'darwin') { | ||||||
|  |     options.execPath = process.helperExecPath; | ||||||
|  |   } | ||||||
|  |   return originalFork(modulePath, args, options); | ||||||
|  | }; | ||||||
|  | @ -1,5 +1,3 @@ | ||||||
| refactor_alter_child_process_fork_to_use_execute_script_with.patch |  | ||||||
| feat_initialize_asar_support.patch |  | ||||||
| expose_get_builtin_module_function.patch | expose_get_builtin_module_function.patch | ||||||
| build_add_gn_build_files.patch | build_add_gn_build_files.patch | ||||||
| fix_add_default_values_for_variables_in_common_gypi.patch | fix_add_default_values_for_variables_in_common_gypi.patch | ||||||
|  | @ -46,3 +44,4 @@ build_do_not_rely_on_gn_helpers_in_gn_build.patch | ||||||
| test_make_test-node-output-v8-warning_generic.patch | test_make_test-node-output-v8-warning_generic.patch | ||||||
| test_match_wpt_streams_transferable_transform-stream-members_any_js.patch | test_match_wpt_streams_transferable_transform-stream-members_any_js.patch | ||||||
| build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch | build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch | ||||||
|  | src_preload_function_for_environment.patch | ||||||
|  |  | ||||||
|  | @ -26,10 +26,10 @@ index 1f3b719048f2477de183e2856b9b8eee8502f708..21116088c101f4679b5a5f41762ce710 | ||||||
|          try { |          try { | ||||||
|            resolvedArgv = Module._resolveFilename(process.argv[1], null, false); |            resolvedArgv = Module._resolveFilename(process.argv[1], null, false); | ||||||
| diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
 | diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
 | ||||||
| index fc8f61ee6d30cf18951ec7a5eb5f09a9583a85ae..61858f6bdcdbc231d7e2327e42732ad928d47ac7 100644
 | index 9142fed75e9050fcc17c01208e82f1bc57923fcd..157a85623c7eb5338baa77aba5dc448a4614ded0 100644
 | ||||||
| --- a/lib/internal/process/pre_execution.js
 | --- a/lib/internal/process/pre_execution.js
 | ||||||
| +++ b/lib/internal/process/pre_execution.js
 | +++ b/lib/internal/process/pre_execution.js
 | ||||||
| @@ -238,12 +238,14 @@ function patchProcessObject(expandArgv1) {
 | @@ -232,12 +232,14 @@ function patchProcessObject(expandArgv1) {
 | ||||||
|    if (expandArgv1 && process.argv[1] && |    if (expandArgv1 && process.argv[1] && | ||||||
|        !StringPrototypeStartsWith(process.argv[1], '-')) { |        !StringPrototypeStartsWith(process.argv[1], '-')) { | ||||||
|      // Expand process.argv[1] into a full path. |      // Expand process.argv[1] into a full path. | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ to child processes spawned with `ELECTRON_RUN_AS_NODE` which is used | ||||||
| by the crashpad client to connect with the handler process. | by the crashpad client to connect with the handler process. | ||||||
| 
 | 
 | ||||||
| diff --git a/lib/child_process.js b/lib/child_process.js
 | diff --git a/lib/child_process.js b/lib/child_process.js
 | ||||||
| index 9dd33ecbac3a5d516f9bff76fdbe1a8aece531f2..0464ecc7b53389cdff97a7fe4cb01582e8b72dbb 100644
 | index 449013906e93e59568a90264d5372a3962db6cb0..168163001f13b641bc284fd01a71f075e1ada94f 100644
 | ||||||
| --- a/lib/child_process.js
 | --- a/lib/child_process.js
 | ||||||
| +++ b/lib/child_process.js
 | +++ b/lib/child_process.js
 | ||||||
| @@ -61,6 +61,7 @@ let debug = require('internal/util/debuglog').debuglog(
 | @@ -61,6 +61,7 @@ let debug = require('internal/util/debuglog').debuglog(
 | ||||||
|  | @ -19,7 +19,7 @@ index 9dd33ecbac3a5d516f9bff76fdbe1a8aece531f2..0464ecc7b53389cdff97a7fe4cb01582 | ||||||
|   |   | ||||||
|  const { |  const { | ||||||
|    AbortError, |    AbortError, | ||||||
| @@ -162,7 +163,6 @@ function fork(modulePath, args = [], options) {
 | @@ -154,7 +155,6 @@ function fork(modulePath, args = [], options) {
 | ||||||
|        ArrayPrototypeSplice(execArgv, index - 1, 2); |        ArrayPrototypeSplice(execArgv, index - 1, 2); | ||||||
|      } |      } | ||||||
|    } |    } | ||||||
|  | @ -27,7 +27,7 @@ index 9dd33ecbac3a5d516f9bff76fdbe1a8aece531f2..0464ecc7b53389cdff97a7fe4cb01582 | ||||||
|    args = [...execArgv, modulePath, ...args]; |    args = [...execArgv, modulePath, ...args]; | ||||||
|   |   | ||||||
|    if (typeof options.stdio === 'string') { |    if (typeof options.stdio === 'string') { | ||||||
| @@ -625,6 +625,21 @@ function normalizeSpawnArguments(file, args, options) {
 | @@ -617,6 +617,21 @@ function normalizeSpawnArguments(file, args, options) {
 | ||||||
|                      'options.windowsVerbatimArguments'); |                      'options.windowsVerbatimArguments'); | ||||||
|    } |    } | ||||||
|   |   | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Shelley Vohr <shelley.vohr@gmail.com> |  | ||||||
| Date: Thu, 13 Sep 2018 08:56:07 -0700 |  | ||||||
| Subject: feat: initialize asar support |  | ||||||
| 
 |  | ||||||
| This patch initializes asar support in Node.js. |  | ||||||
| 
 |  | ||||||
| diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
 |  | ||||||
| index 9142fed75e9050fcc17c01208e82f1bc57923fcd..fc8f61ee6d30cf18951ec7a5eb5f09a9583a85ae 100644
 |  | ||||||
| --- a/lib/internal/process/pre_execution.js
 |  | ||||||
| +++ b/lib/internal/process/pre_execution.js
 |  | ||||||
| @@ -87,6 +87,7 @@ function prepareShadowRealmExecution() {
 |  | ||||||
|    }); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +let processLinkedBinding = process._linkedBinding;
 |  | ||||||
|  function prepareExecution(options) { |  | ||||||
|    const { expandArgv1, initializeModules, isMainThread } = options; |  | ||||||
|   |  | ||||||
| @@ -193,12 +194,17 @@ function setupUserModules(forceDefaultLoader = false) {
 |  | ||||||
|    } |  | ||||||
|    // Need to be done after --require setup. |  | ||||||
|    initializeFrozenIntrinsics(); |  | ||||||
| +  setupAsarSupport();
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  function refreshRuntimeOptions() { |  | ||||||
|    refreshOptions(); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +function setupAsarSupport() {
 |  | ||||||
| +  processLinkedBinding('electron_common_asar').initAsarSupport(require);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  /** |  | ||||||
|   * Patch the process object with legacy properties and normalizations. |  | ||||||
|   * Replace `process.argv[0]` with `process.execPath`, preserving the original `argv[0]` value as `process.argv0`. |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Shelley Vohr <shelley.vohr@gmail.com> |  | ||||||
| Date: Mon, 30 Jul 2018 10:30:35 -0700 |  | ||||||
| Subject: refactor: alter child_process.fork to use execute script with |  | ||||||
|  Electron |  | ||||||
| 
 |  | ||||||
| When forking a child script, we setup a special environment to make the Electron binary run like the upstream node. On Mac, we use the helper app as node binary. |  | ||||||
| 
 |  | ||||||
| diff --git a/lib/child_process.js b/lib/child_process.js
 |  | ||||||
| index 449013906e93e59568a90264d5372a3962db6cb0..9dd33ecbac3a5d516f9bff76fdbe1a8aece531f2 100644
 |  | ||||||
| --- a/lib/child_process.js
 |  | ||||||
| +++ b/lib/child_process.js
 |  | ||||||
| @@ -139,6 +139,14 @@ function fork(modulePath, args = [], options) {
 |  | ||||||
|      validateObject(options, 'options'); |  | ||||||
|    } |  | ||||||
|    options = { __proto__: null, ...options, shell: false }; |  | ||||||
| +  // When forking a child script, we setup a special environment to make
 |  | ||||||
| +  // the electron binary run like upstream Node.js
 |  | ||||||
| +  options.env = Object.create(options.env || process.env)
 |  | ||||||
| +  options.env.ELECTRON_RUN_AS_NODE = 1;
 |  | ||||||
| +
 |  | ||||||
| +  if (!options.execPath && process.type && process.platform == 'darwin') {
 |  | ||||||
| +     options.execPath = process.helperExecPath;
 |  | ||||||
| +  }
 |  | ||||||
|    options.execPath = options.execPath || process.execPath; |  | ||||||
|    validateArgumentNullCheck(options.execPath, 'options.execPath'); |  | ||||||
|   |  | ||||||
							
								
								
									
										299
									
								
								patches/node/src_preload_function_for_environment.patch
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								patches/node/src_preload_function_for_environment.patch
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,299 @@ | ||||||
|  | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Cheng Zhao <zcbenz@gmail.com> | ||||||
|  | Date: Mon, 22 Jan 2024 13:45:55 +0900 | ||||||
|  | Subject: src: preload function for Environment | ||||||
|  | 
 | ||||||
|  | https://github.com/nodejs/node/pull/51539 | ||||||
|  | 
 | ||||||
|  | This PR adds a |preload| arg to the node::CreateEnvironment to allow | ||||||
|  | embedders to set a preload function for the environment, which will run | ||||||
|  | after the environment is loaded and before the main script runs. | ||||||
|  | 
 | ||||||
|  | This is similiar to the --require CLI option, but runs a C++ function, | ||||||
|  | and can only be set by embedders. | ||||||
|  | 
 | ||||||
|  | The preload function can be used by embedders to inject scripts before | ||||||
|  | running the main script, for example: | ||||||
|  | 1. In Electron it is used to initialize the ASAR virtual filesystem, | ||||||
|  |    inject custom process properties, etc. | ||||||
|  | 2. In VS Code it can be used to reset the module search paths for | ||||||
|  |    extensions. | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
 | ||||||
|  | index 157a85623c7eb5338baa77aba5dc448a4614ded0..701f91f1c9603c1da03e0fe6d20c8627c8d644fb 100644
 | ||||||
|  | --- a/lib/internal/process/pre_execution.js
 | ||||||
|  | +++ b/lib/internal/process/pre_execution.js
 | ||||||
|  | @@ -185,6 +185,9 @@ function setupUserModules(forceDefaultLoader = false) {
 | ||||||
|  |    initializeESMLoader(forceDefaultLoader); | ||||||
|  |    const CJSLoader = require('internal/modules/cjs/loader'); | ||||||
|  |    assert(!CJSLoader.hasLoadedAnyUserCJSModule); | ||||||
|  | +  if (getEmbedderOptions().hasEmbedderPreload) {
 | ||||||
|  | +    runEmbedderPreload();
 | ||||||
|  | +  }
 | ||||||
|  |    // Do not enable preload modules if custom loaders are disabled. | ||||||
|  |    // For example, loader workers are responsible for doing this themselves. | ||||||
|  |    // And preload modules are not supported in ShadowRealm as well. | ||||||
|  | @@ -742,6 +745,10 @@ function initializeFrozenIntrinsics() {
 | ||||||
|  |    } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +function runEmbedderPreload() {
 | ||||||
|  | +  internalBinding('mksnapshot').runEmbedderPreload(process, require);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  function loadPreloadModules() { | ||||||
|  |    // For user code, we preload modules if `-r` is passed | ||||||
|  |    const preloadModules = getOptionValue('--require'); | ||||||
|  | diff --git a/src/api/environment.cc b/src/api/environment.cc
 | ||||||
|  | index 9045de3b17c93c4864a1bb1024b08f7d1ffa83be..7c580e1ce1af66e010083240aaf8b0037dd41f2e 100644
 | ||||||
|  | --- a/src/api/environment.cc
 | ||||||
|  | +++ b/src/api/environment.cc
 | ||||||
|  | @@ -442,7 +442,8 @@ Environment* CreateEnvironment(
 | ||||||
|  |      const std::vector<std::string>& exec_args, | ||||||
|  |      EnvironmentFlags::Flags flags, | ||||||
|  |      ThreadId thread_id, | ||||||
|  | -    std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
 | ||||||
|  | +    std::unique_ptr<InspectorParentHandle> inspector_parent_handle,
 | ||||||
|  | +    EmbedderPreloadCallback preload) {
 | ||||||
|  |    Isolate* isolate = isolate_data->isolate(); | ||||||
|  |   | ||||||
|  |    Isolate::Scope isolate_scope(isolate); | ||||||
|  | @@ -463,7 +464,8 @@ Environment* CreateEnvironment(
 | ||||||
|  |                                       exec_args, | ||||||
|  |                                       env_snapshot_info, | ||||||
|  |                                       flags, | ||||||
|  | -                                     thread_id);
 | ||||||
|  | +                                     thread_id,
 | ||||||
|  | +                                     std::move(preload));
 | ||||||
|  |    CHECK_NOT_NULL(env); | ||||||
|  |   | ||||||
|  |    if (use_snapshot) { | ||||||
|  | diff --git a/src/env-inl.h b/src/env-inl.h
 | ||||||
|  | index 564de2990c09a54693686666f9ad66398ff76ab5..b10bc2396539b011dec6f09719251bfc842072af 100644
 | ||||||
|  | --- a/src/env-inl.h
 | ||||||
|  | +++ b/src/env-inl.h
 | ||||||
|  | @@ -438,6 +438,10 @@ inline void Environment::set_embedder_entry_point(StartExecutionCallback&& fn) {
 | ||||||
|  |    embedder_entry_point_ = std::move(fn); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +inline const EmbedderPreloadCallback& Environment::embedder_preload() const {
 | ||||||
|  | +  return embedder_preload_;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  inline double Environment::new_async_id() { | ||||||
|  |    async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1; | ||||||
|  |    return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter]; | ||||||
|  | diff --git a/src/env.cc b/src/env.cc
 | ||||||
|  | index ba575a04340b91709fb6c8710ab160a4ca1f8b77..76db0ac4ef72b902a7567a96cfd751ff879117b7 100644
 | ||||||
|  | --- a/src/env.cc
 | ||||||
|  | +++ b/src/env.cc
 | ||||||
|  | @@ -767,7 +767,8 @@ Environment::Environment(IsolateData* isolate_data,
 | ||||||
|  |                           const std::vector<std::string>& exec_args, | ||||||
|  |                           const EnvSerializeInfo* env_info, | ||||||
|  |                           EnvironmentFlags::Flags flags, | ||||||
|  | -                         ThreadId thread_id)
 | ||||||
|  | +                         ThreadId thread_id,
 | ||||||
|  | +                         EmbedderPreloadCallback preload)
 | ||||||
|  |      : isolate_(isolate), | ||||||
|  |        isolate_data_(isolate_data), | ||||||
|  |        async_hooks_(isolate, MAYBE_FIELD_PTR(env_info, async_hooks)), | ||||||
|  | @@ -793,7 +794,8 @@ Environment::Environment(IsolateData* isolate_data,
 | ||||||
|  |        flags_(flags), | ||||||
|  |        thread_id_(thread_id.id == static_cast<uint64_t>(-1) | ||||||
|  |                       ? AllocateEnvironmentThreadId().id | ||||||
|  | -                     : thread_id.id) {
 | ||||||
|  | +                     : thread_id.id),
 | ||||||
|  | +      embedder_preload_(std::move(preload)) {
 | ||||||
|  |    constexpr bool is_shared_ro_heap = | ||||||
|  |  #ifdef NODE_V8_SHARED_RO_HEAP | ||||||
|  |        true; | ||||||
|  | diff --git a/src/env.h b/src/env.h
 | ||||||
|  | index 448075e354c760a2dbd1dd763f40b7a645730250..a5aad9596953536b0a1f741dfbc4f21f6a961404 100644
 | ||||||
|  | --- a/src/env.h
 | ||||||
|  | +++ b/src/env.h
 | ||||||
|  | @@ -635,7 +635,8 @@ class Environment : public MemoryRetainer {
 | ||||||
|  |                const std::vector<std::string>& exec_args, | ||||||
|  |                const EnvSerializeInfo* env_info, | ||||||
|  |                EnvironmentFlags::Flags flags, | ||||||
|  | -              ThreadId thread_id);
 | ||||||
|  | +              ThreadId thread_id,
 | ||||||
|  | +              EmbedderPreloadCallback preload);
 | ||||||
|  |    void InitializeMainContext(v8::Local<v8::Context> context, | ||||||
|  |                               const EnvSerializeInfo* env_info); | ||||||
|  |    ~Environment() override; | ||||||
|  | @@ -986,6 +987,8 @@ class Environment : public MemoryRetainer {
 | ||||||
|  |    inline const StartExecutionCallback& embedder_entry_point() const; | ||||||
|  |    inline void set_embedder_entry_point(StartExecutionCallback&& fn); | ||||||
|  |   | ||||||
|  | +  inline const EmbedderPreloadCallback& embedder_preload() const;
 | ||||||
|  | +
 | ||||||
|  |    inline void set_process_exit_handler( | ||||||
|  |        std::function<void(Environment*, ExitCode)>&& handler); | ||||||
|  |   | ||||||
|  | @@ -1186,6 +1189,7 @@ class Environment : public MemoryRetainer {
 | ||||||
|  |   | ||||||
|  |    builtins::BuiltinLoader builtin_loader_; | ||||||
|  |    StartExecutionCallback embedder_entry_point_; | ||||||
|  | +  EmbedderPreloadCallback embedder_preload_;
 | ||||||
|  |   | ||||||
|  |    // Used by allocate_managed_buffer() and release_managed_buffer() to keep | ||||||
|  |    // track of the BackingStore for a given pointer. | ||||||
|  | diff --git a/src/node.h b/src/node.h
 | ||||||
|  | index 36da93a7b41ea450a5f288ec17b61adae46ae178..09e044e86bab2cef42c86dbfc9bbcc743daf564d 100644
 | ||||||
|  | --- a/src/node.h
 | ||||||
|  | +++ b/src/node.h
 | ||||||
|  | @@ -678,11 +678,23 @@ struct InspectorParentHandle {
 | ||||||
|  |    virtual ~InspectorParentHandle() = default; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +using EmbedderPreloadCallback =
 | ||||||
|  | +    std::function<void(Environment* env,
 | ||||||
|  | +                       v8::Local<v8::Value> process,
 | ||||||
|  | +                       v8::Local<v8::Value> require)>;
 | ||||||
|  | +
 | ||||||
|  |  // TODO(addaleax): Maybe move per-Environment options parsing here. | ||||||
|  |  // Returns nullptr when the Environment cannot be created e.g. there are | ||||||
|  |  // pending JavaScript exceptions. | ||||||
|  |  // `context` may be empty if an `EmbedderSnapshotData` instance was provided | ||||||
|  |  // to `NewIsolate()` and `CreateIsolateData()`. | ||||||
|  | +//
 | ||||||
|  | +// The |preload| function will run before executing the entry point, which
 | ||||||
|  | +// is usually used by embedders to inject scripts. The function is executed
 | ||||||
|  | +// with preload(process, require), and the passed require function has access
 | ||||||
|  | +// to internal Node.js modules. The |preload| function is inherited by worker
 | ||||||
|  | +// threads and thus will run in work threads, so make sure the function is
 | ||||||
|  | +// thread-safe.
 | ||||||
|  |  NODE_EXTERN Environment* CreateEnvironment( | ||||||
|  |      IsolateData* isolate_data, | ||||||
|  |      v8::Local<v8::Context> context, | ||||||
|  | @@ -690,7 +702,8 @@ NODE_EXTERN Environment* CreateEnvironment(
 | ||||||
|  |      const std::vector<std::string>& exec_args, | ||||||
|  |      EnvironmentFlags::Flags flags = EnvironmentFlags::kDefaultFlags, | ||||||
|  |      ThreadId thread_id = {} /* allocates a thread id automatically */, | ||||||
|  | -    std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
 | ||||||
|  | +    std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {},
 | ||||||
|  | +    EmbedderPreloadCallback preload = nullptr);
 | ||||||
|  |   | ||||||
|  |  // Returns a handle that can be passed to `LoadEnvironment()`, making the | ||||||
|  |  // child Environment accessible to the inspector as if it were a Node.js Worker. | ||||||
|  | diff --git a/src/node_options.cc b/src/node_options.cc
 | ||||||
|  | index 48ce3f3b68a94fc35e5ce93a385ddbebb03741b9..39d34e18e483882a71145110962109711a1566e2 100644
 | ||||||
|  | --- a/src/node_options.cc
 | ||||||
|  | +++ b/src/node_options.cc
 | ||||||
|  | @@ -1290,6 +1290,12 @@ void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) {
 | ||||||
|  |            .IsNothing()) | ||||||
|  |      return; | ||||||
|  |   | ||||||
|  | +  if (ret->Set(context,
 | ||||||
|  | +               FIXED_ONE_BYTE_STRING(env->isolate(), "hasEmbedderPreload"),
 | ||||||
|  | +               Boolean::New(isolate, env->embedder_preload() != nullptr))
 | ||||||
|  | +          .IsNothing())
 | ||||||
|  | +    return;
 | ||||||
|  | +
 | ||||||
|  |    args.GetReturnValue().Set(ret); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc
 | ||||||
|  | index 562a47ddcc9c8e61590b7b09d84dc08ab4b3653d..325bebc1df9ad2e8b0bad468951cf1563ecefc14 100644
 | ||||||
|  | --- a/src/node_snapshotable.cc
 | ||||||
|  | +++ b/src/node_snapshotable.cc
 | ||||||
|  | @@ -1369,6 +1369,13 @@ static void RunEmbedderEntryPoint(const FunctionCallbackInfo<Value>& args) {
 | ||||||
|  |    } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void RunEmbedderPreload(const FunctionCallbackInfo<Value>& args) {
 | ||||||
|  | +  Environment* env = Environment::GetCurrent(args);
 | ||||||
|  | +  CHECK(env->embedder_preload());
 | ||||||
|  | +  CHECK_EQ(args.Length(), 2);
 | ||||||
|  | +  env->embedder_preload()(env, args[0], args[1]);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  void CompileSerializeMain(const FunctionCallbackInfo<Value>& args) { | ||||||
|  |    CHECK(args[0]->IsString()); | ||||||
|  |    Local<String> filename = args[0].As<String>(); | ||||||
|  | @@ -1493,6 +1500,7 @@ void CreatePerIsolateProperties(IsolateData* isolate_data,
 | ||||||
|  |                                  Local<ObjectTemplate> target) { | ||||||
|  |    Isolate* isolate = isolate_data->isolate(); | ||||||
|  |    SetMethod(isolate, target, "runEmbedderEntryPoint", RunEmbedderEntryPoint); | ||||||
|  | +  SetMethod(isolate, target, "runEmbedderPreload", RunEmbedderPreload);
 | ||||||
|  |    SetMethod(isolate, target, "compileSerializeMain", CompileSerializeMain); | ||||||
|  |    SetMethod(isolate, target, "setSerializeCallback", SetSerializeCallback); | ||||||
|  |    SetMethod(isolate, target, "setDeserializeCallback", SetDeserializeCallback); | ||||||
|  | @@ -1506,6 +1514,7 @@ void CreatePerIsolateProperties(IsolateData* isolate_data,
 | ||||||
|  |   | ||||||
|  |  void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | ||||||
|  |    registry->Register(RunEmbedderEntryPoint); | ||||||
|  | +  registry->Register(RunEmbedderPreload);
 | ||||||
|  |    registry->Register(CompileSerializeMain); | ||||||
|  |    registry->Register(SetSerializeCallback); | ||||||
|  |    registry->Register(SetDeserializeCallback); | ||||||
|  | diff --git a/src/node_worker.cc b/src/node_worker.cc
 | ||||||
|  | index 900674bbe4c90e9aeb2013c06c9979864b06dcd5..2a22d986585e93ea00c6dcdca1f7b783ef0723f8 100644
 | ||||||
|  | --- a/src/node_worker.cc
 | ||||||
|  | +++ b/src/node_worker.cc
 | ||||||
|  | @@ -63,6 +63,7 @@ Worker::Worker(Environment* env,
 | ||||||
|  |        thread_id_(AllocateEnvironmentThreadId()), | ||||||
|  |        name_(name), | ||||||
|  |        env_vars_(env_vars), | ||||||
|  | +      embedder_preload_(env->embedder_preload()),
 | ||||||
|  |        snapshot_data_(snapshot_data) { | ||||||
|  |    Debug(this, "Creating new worker instance with thread id %llu", | ||||||
|  |          thread_id_.id); | ||||||
|  | @@ -360,7 +361,8 @@ void Worker::Run() {
 | ||||||
|  |              std::move(exec_argv_), | ||||||
|  |              static_cast<EnvironmentFlags::Flags>(environment_flags_), | ||||||
|  |              thread_id_, | ||||||
|  | -            std::move(inspector_parent_handle_)));
 | ||||||
|  | +            std::move(inspector_parent_handle_),
 | ||||||
|  | +            std::move(embedder_preload_)));
 | ||||||
|  |          if (is_stopped()) return; | ||||||
|  |          CHECK_NOT_NULL(env_); | ||||||
|  |          env_->set_env_vars(std::move(env_vars_)); | ||||||
|  | diff --git a/src/node_worker.h b/src/node_worker.h
 | ||||||
|  | index 531e2b5287010f9206ab4fd7f4dd0f3dec9fe55c..07fd7b460654e169e8b6822474dc3cc70fcec4c0 100644
 | ||||||
|  | --- a/src/node_worker.h
 | ||||||
|  | +++ b/src/node_worker.h
 | ||||||
|  | @@ -114,6 +114,7 @@ class Worker : public AsyncWrap {
 | ||||||
|  |   | ||||||
|  |    std::unique_ptr<MessagePortData> child_port_data_; | ||||||
|  |    std::shared_ptr<KVStore> env_vars_; | ||||||
|  | +  EmbedderPreloadCallback embedder_preload_;
 | ||||||
|  |   | ||||||
|  |    // A raw flag that is used by creator and worker threads to | ||||||
|  |    // sync up on pre-mature termination of worker  - while in the | ||||||
|  | diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc
 | ||||||
|  | index 2e747c7be58922897abd0424b797f3f12a89ada1..658f8df4b01d60759e858cf5283b9be9467dd142 100644
 | ||||||
|  | --- a/test/cctest/test_environment.cc
 | ||||||
|  | +++ b/test/cctest/test_environment.cc
 | ||||||
|  | @@ -773,3 +773,31 @@ TEST_F(EnvironmentTest, RequestInterruptAtExit) {
 | ||||||
|  |   | ||||||
|  |    context->Exit(); | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  | +TEST_F(EnvironmentTest, EmbedderPreload) {
 | ||||||
|  | +  v8::HandleScope handle_scope(isolate_);
 | ||||||
|  | +  v8::Local<v8::Context> context = node::NewContext(isolate_);
 | ||||||
|  | +  v8::Context::Scope context_scope(context);
 | ||||||
|  | +
 | ||||||
|  | +  node::EmbedderPreloadCallback preload = [](node::Environment* env,
 | ||||||
|  | +                                             v8::Local<v8::Value> process,
 | ||||||
|  | +                                             v8::Local<v8::Value> require) {
 | ||||||
|  | +    CHECK(process->IsObject());
 | ||||||
|  | +    CHECK(require->IsFunction());
 | ||||||
|  | +    process.As<v8::Object>()->Set(
 | ||||||
|  | +        env->context(),
 | ||||||
|  | +        v8::String::NewFromUtf8Literal(env->isolate(), "prop"),
 | ||||||
|  | +        v8::String::NewFromUtf8Literal(env->isolate(), "preload")).Check();
 | ||||||
|  | +  };
 | ||||||
|  | +
 | ||||||
|  | +  std::unique_ptr<node::Environment, decltype(&node::FreeEnvironment)> env(
 | ||||||
|  | +      node::CreateEnvironment(isolate_data_, context, {}, {},
 | ||||||
|  | +                              node::EnvironmentFlags::kDefaultFlags, {}, {},
 | ||||||
|  | +                              preload),
 | ||||||
|  | +      node::FreeEnvironment);
 | ||||||
|  | +
 | ||||||
|  | +  v8::Local<v8::Value> main_ret =
 | ||||||
|  | +      node::LoadEnvironment(env.get(), "return process.prop;").ToLocalChecked();
 | ||||||
|  | +  node::Utf8Value main_ret_str(isolate_, main_ret);
 | ||||||
|  | +  EXPECT_EQ(std::string(*main_ret_str), "preload");
 | ||||||
|  | +}
 | ||||||
|  | @ -38,8 +38,8 @@ const main = async () => { | ||||||
|       config: 'webpack.config.worker.js' |       config: 'webpack.config.worker.js' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       name: 'asar_bundle_deps', |       name: 'node_bundle_deps', | ||||||
|       config: 'webpack.config.asar.js' |       config: 'webpack.config.node.js' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       name: 'utility_bundle_deps', |       name: 'utility_bundle_deps', | ||||||
|  |  | ||||||
|  | @ -21,7 +21,6 @@ | ||||||
| #include "base/task/single_thread_task_runner.h" | #include "base/task/single_thread_task_runner.h" | ||||||
| #include "base/task/thread_pool/thread_pool_instance.h" | #include "base/task/thread_pool/thread_pool_instance.h" | ||||||
| #include "content/public/common/content_switches.h" | #include "content/public/common/content_switches.h" | ||||||
| #include "electron/electron_version.h" |  | ||||||
| #include "electron/fuses.h" | #include "electron/fuses.h" | ||||||
| #include "gin/array_buffer.h" | #include "gin/array_buffer.h" | ||||||
| #include "gin/public/isolate_holder.h" | #include "gin/public/isolate_holder.h" | ||||||
|  | @ -260,7 +259,8 @@ int NodeMain(int argc, char* argv[]) { | ||||||
|       env = node::CreateEnvironment( |       env = node::CreateEnvironment( | ||||||
|           isolate_data, isolate->GetCurrentContext(), result->args(), |           isolate_data, isolate->GetCurrentContext(), result->args(), | ||||||
|           result->exec_args(), |           result->exec_args(), | ||||||
|           static_cast<node::EnvironmentFlags::Flags>(env_flags)); |           static_cast<node::EnvironmentFlags::Flags>(env_flags), {}, {}, | ||||||
|  |           &OnNodePreload); | ||||||
|       CHECK_NE(nullptr, env); |       CHECK_NE(nullptr, env); | ||||||
| 
 | 
 | ||||||
|       node::SetIsolateUpForNode(isolate); |       node::SetIsolateUpForNode(isolate); | ||||||
|  | @ -282,11 +282,6 @@ int NodeMain(int argc, char* argv[]) { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|       process.Set("crashReporter", reporter); |       process.Set("crashReporter", reporter); | ||||||
| 
 |  | ||||||
|       gin_helper::Dictionary versions; |  | ||||||
|       if (process.Get("versions", &versions)) { |  | ||||||
|         versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     v8::HandleScope scope(isolate); |     v8::HandleScope scope(isolate); | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ | ||||||
| #include "shell/common/gin_converters/file_path_converter.h" | #include "shell/common/gin_converters/file_path_converter.h" | ||||||
| #include "shell/common/gin_helper/dictionary.h" | #include "shell/common/gin_helper/dictionary.h" | ||||||
| #include "shell/common/node_includes.h" | #include "shell/common/node_includes.h" | ||||||
| #include "shell/common/node_util.h" |  | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
|  | @ -191,19 +190,6 @@ class Archive : public node::ObjectWrap { | ||||||
|   std::shared_ptr<asar::Archive> archive_; |   std::shared_ptr<asar::Archive> archive_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void InitAsarSupport(const v8::FunctionCallbackInfo<v8::Value>& args) { |  | ||||||
|   auto* isolate = args.GetIsolate(); |  | ||||||
|   auto require = args[0]; |  | ||||||
| 
 |  | ||||||
|   // Evaluate asar_bundle.js.
 |  | ||||||
|   std::vector<v8::Local<v8::String>> asar_bundle_params = { |  | ||||||
|       node::FIXED_ONE_BYTE_STRING(isolate, "require")}; |  | ||||||
|   std::vector<v8::Local<v8::Value>> asar_bundle_args = {require}; |  | ||||||
|   electron::util::CompileAndCall(isolate->GetCurrentContext(), |  | ||||||
|                                  "electron/js2c/asar_bundle", |  | ||||||
|                                  &asar_bundle_params, &asar_bundle_args); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SplitPath(const v8::FunctionCallbackInfo<v8::Value>& args) { | static void SplitPath(const v8::FunctionCallbackInfo<v8::Value>& args) { | ||||||
|   auto* isolate = args.GetIsolate(); |   auto* isolate = args.GetIsolate(); | ||||||
| 
 | 
 | ||||||
|  | @ -239,7 +225,6 @@ void Initialize(v8::Local<v8::Object> exports, | ||||||
|   exports->Set(context, node::FIXED_ONE_BYTE_STRING(isolate, "Archive"), cons) |   exports->Set(context, node::FIXED_ONE_BYTE_STRING(isolate, "Archive"), cons) | ||||||
|       .Check(); |       .Check(); | ||||||
|   NODE_SET_METHOD(exports, "splitPath", &SplitPath); |   NODE_SET_METHOD(exports, "splitPath", &SplitPath); | ||||||
|   NODE_SET_METHOD(exports, "initAsarSupport", &InitAsarSupport); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace
 | }  // namespace
 | ||||||
|  |  | ||||||
|  | @ -15,8 +15,6 @@ | ||||||
| #include "base/process/process_handle.h" | #include "base/process/process_handle.h" | ||||||
| #include "base/process/process_metrics_iocounters.h" | #include "base/process/process_metrics_iocounters.h" | ||||||
| #include "base/system/sys_info.h" | #include "base/system/sys_info.h" | ||||||
| #include "chrome/common/chrome_version.h" |  | ||||||
| #include "electron/electron_version.h" |  | ||||||
| #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" | #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" | ||||||
| #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" | #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" | ||||||
| #include "shell/browser/browser.h" | #include "shell/browser/browser.h" | ||||||
|  | @ -84,12 +82,6 @@ void ElectronBindings::BindTo(v8::Isolate* isolate, | ||||||
|   dict.SetMethod("activateUvLoop", |   dict.SetMethod("activateUvLoop", | ||||||
|                  base::BindRepeating(&ElectronBindings::ActivateUVLoop, |                  base::BindRepeating(&ElectronBindings::ActivateUVLoop, | ||||||
|                                      base::Unretained(this))); |                                      base::Unretained(this))); | ||||||
| 
 |  | ||||||
|   gin_helper::Dictionary versions; |  | ||||||
|   if (dict.Get("versions", &versions)) { |  | ||||||
|     versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING); |  | ||||||
|     versions.SetReadOnly("chrome", CHROME_VERSION_STRING); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ElectronBindings::EnvironmentDestroyed(node::Environment* env) { | void ElectronBindings::EnvironmentDestroyed(node::Environment* env) { | ||||||
|  |  | ||||||
|  | @ -20,9 +20,11 @@ | ||||||
| #include "base/strings/utf_string_conversions.h" | #include "base/strings/utf_string_conversions.h" | ||||||
| #include "base/task/single_thread_task_runner.h" | #include "base/task/single_thread_task_runner.h" | ||||||
| #include "base/trace_event/trace_event.h" | #include "base/trace_event/trace_event.h" | ||||||
|  | #include "chrome/common/chrome_version.h" | ||||||
| #include "content/public/browser/browser_thread.h" | #include "content/public/browser/browser_thread.h" | ||||||
| #include "content/public/common/content_paths.h" | #include "content/public/common/content_paths.h" | ||||||
| #include "electron/buildflags/buildflags.h" | #include "electron/buildflags/buildflags.h" | ||||||
|  | #include "electron/electron_version.h" | ||||||
| #include "electron/fuses.h" | #include "electron/fuses.h" | ||||||
| #include "shell/browser/api/electron_api_app.h" | #include "shell/browser/api/electron_api_app.h" | ||||||
| #include "shell/common/api/electron_bindings.h" | #include "shell/common/api/electron_bindings.h" | ||||||
|  | @ -34,6 +36,7 @@ | ||||||
| #include "shell/common/gin_helper/event_emitter_caller.h" | #include "shell/common/gin_helper/event_emitter_caller.h" | ||||||
| #include "shell/common/gin_helper/microtasks_scope.h" | #include "shell/common/gin_helper/microtasks_scope.h" | ||||||
| #include "shell/common/mac/main_application_bundle.h" | #include "shell/common/mac/main_application_bundle.h" | ||||||
|  | #include "shell/common/node_util.h" | ||||||
| #include "shell/common/world_ids.h" | #include "shell/common/world_ids.h" | ||||||
| #include "third_party/blink/public/web/web_local_frame.h" | #include "third_party/blink/public/web/web_local_frame.h" | ||||||
| #include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"  // nogncheck
 | #include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"  // nogncheck
 | ||||||
|  | @ -610,7 +613,6 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment( | ||||||
|                          electron::fuses::IsOnlyLoadAppFromAsarEnabled())); |                          electron::fuses::IsOnlyLoadAppFromAsarEnabled())); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   base::FilePath resources_path = GetResourcesPath(); |  | ||||||
|   std::string init_script = "electron/js2c/" + process_type + "_init"; |   std::string init_script = "electron/js2c/" + process_type + "_init"; | ||||||
| 
 | 
 | ||||||
|   args.insert(args.begin() + 1, init_script); |   args.insert(args.begin() + 1, init_script); | ||||||
|  | @ -649,7 +651,8 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment( | ||||||
|     v8::TryCatch try_catch(isolate); |     v8::TryCatch try_catch(isolate); | ||||||
|     env = node::CreateEnvironment( |     env = node::CreateEnvironment( | ||||||
|         static_cast<node::IsolateData*>(isolate_data), context, args, exec_args, |         static_cast<node::IsolateData*>(isolate_data), context, args, exec_args, | ||||||
|         static_cast<node::EnvironmentFlags::Flags>(env_flags)); |         static_cast<node::EnvironmentFlags::Flags>(env_flags), {}, {}, | ||||||
|  |         &OnNodePreload); | ||||||
| 
 | 
 | ||||||
|     if (try_catch.HasCaught()) { |     if (try_catch.HasCaught()) { | ||||||
|       std::string err_msg = |       std::string err_msg = | ||||||
|  | @ -735,11 +738,6 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment( | ||||||
| 
 | 
 | ||||||
|   gin_helper::Dictionary process(context->GetIsolate(), env->process_object()); |   gin_helper::Dictionary process(context->GetIsolate(), env->process_object()); | ||||||
|   process.SetReadOnly("type", process_type); |   process.SetReadOnly("type", process_type); | ||||||
|   process.Set("resourcesPath", resources_path); |  | ||||||
|   // The path to helper app.
 |  | ||||||
|   base::FilePath helper_exec_path; |  | ||||||
|   base::PathService::Get(content::CHILD_PROCESS_EXE, &helper_exec_path); |  | ||||||
|   process.Set("helperExecPath", helper_exec_path); |  | ||||||
| 
 | 
 | ||||||
|   if (browser_env_ == BrowserEnvironment::kBrowser || |   if (browser_env_ == BrowserEnvironment::kBrowser || | ||||||
|       browser_env_ == BrowserEnvironment::kRenderer) { |       browser_env_ == BrowserEnvironment::kRenderer) { | ||||||
|  | @ -931,4 +929,29 @@ void NodeBindings::EmbedThreadRunner(void* arg) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void OnNodePreload(node::Environment* env, | ||||||
|  |                    v8::Local<v8::Value> process, | ||||||
|  |                    v8::Local<v8::Value> require) { | ||||||
|  |   // Set custom process properties.
 | ||||||
|  |   gin_helper::Dictionary dict(env->isolate(), process.As<v8::Object>()); | ||||||
|  |   dict.SetReadOnly("resourcesPath", GetResourcesPath()); | ||||||
|  |   base::FilePath helper_exec_path;  // path to the helper app.
 | ||||||
|  |   base::PathService::Get(content::CHILD_PROCESS_EXE, &helper_exec_path); | ||||||
|  |   dict.SetReadOnly("helperExecPath", helper_exec_path); | ||||||
|  |   gin_helper::Dictionary versions; | ||||||
|  |   if (dict.Get("versions", &versions)) { | ||||||
|  |     versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING); | ||||||
|  |     versions.SetReadOnly("chrome", CHROME_VERSION_STRING); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Execute lib/node/init.ts.
 | ||||||
|  |   std::vector<v8::Local<v8::String>> bundle_params = { | ||||||
|  |       node::FIXED_ONE_BYTE_STRING(env->isolate(), "process"), | ||||||
|  |       node::FIXED_ONE_BYTE_STRING(env->isolate(), "require"), | ||||||
|  |   }; | ||||||
|  |   std::vector<v8::Local<v8::Value>> bundle_args = {process, require}; | ||||||
|  |   electron::util::CompileAndCall(env->context(), "electron/js2c/node_init", | ||||||
|  |                                  &bundle_params, &bundle_args); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace electron
 | }  // namespace electron
 | ||||||
|  |  | ||||||
|  | @ -219,6 +219,12 @@ class NodeBindings { | ||||||
|   base::WeakPtrFactory<NodeBindings> weak_factory_{this}; |   base::WeakPtrFactory<NodeBindings> weak_factory_{this}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // A thread-safe function responsible for loading preload script which runs for
 | ||||||
|  | // all node environments (including child processes and workers).
 | ||||||
|  | void OnNodePreload(node::Environment* env, | ||||||
|  |                    v8::Local<v8::Value> process, | ||||||
|  |                    v8::Local<v8::Value> require); | ||||||
|  | 
 | ||||||
| }  // namespace electron
 | }  // namespace electron
 | ||||||
| 
 | 
 | ||||||
| #endif  // ELECTRON_SHELL_COMMON_NODE_BINDINGS_H_
 | #endif  // ELECTRON_SHELL_COMMON_NODE_BINDINGS_H_
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include "shell/common/node_util.h" | #include "shell/common/node_util.h" | ||||||
| 
 | 
 | ||||||
| #include "base/logging.h" | #include "base/logging.h" | ||||||
|  | #include "gin/converter.h" | ||||||
| #include "shell/common/node_includes.h" | #include "shell/common/node_includes.h" | ||||||
| 
 | 
 | ||||||
| namespace electron::util { | namespace electron::util { | ||||||
|  | @ -31,7 +32,14 @@ v8::MaybeLocal<v8::Value> CompileAndCall( | ||||||
|   // This will only be caught when something has gone terrible wrong as all
 |   // This will only be caught when something has gone terrible wrong as all
 | ||||||
|   // electron scripts are wrapped in a try {} catch {} by webpack
 |   // electron scripts are wrapped in a try {} catch {} by webpack
 | ||||||
|   if (try_catch.HasCaught()) { |   if (try_catch.HasCaught()) { | ||||||
|     LOG(ERROR) << "Failed to CompileAndCall electron script: " << id; |     std::string msg = "no error message"; | ||||||
|  |     if (!try_catch.Message().IsEmpty()) { | ||||||
|  |       gin::ConvertFromV8(isolate, try_catch.Message()->Get(), &msg); | ||||||
|  |     } else if (try_catch.HasTerminated()) { | ||||||
|  |       msg = "script execution has been terminated"; | ||||||
|  |     } | ||||||
|  |     LOG(ERROR) << "Failed to CompileAndCall electron script (" << id | ||||||
|  |                << "): " << msg; | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								typings/internal-ambient.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								typings/internal-ambient.d.ts
									
										
									
									
										vendored
									
									
								
							|  | @ -90,7 +90,6 @@ declare namespace NodeJS { | ||||||
|       asarPath: string; |       asarPath: string; | ||||||
|       filePath: string; |       filePath: string; | ||||||
|     }; |     }; | ||||||
|     initAsarSupport(require: NodeJS.Require): void; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   interface NetBinding { |   interface NetBinding { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cheng Zhao
				Cheng Zhao