From 486e53a4f84a9c40f65e5a2f5c9e888d6f7ad311 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 10:02:52 +0000 Subject: [PATCH 1/3] fix: expose the built-in electron module via the ESM loader Co-authored-by: Samuel Attard --- patches/node/.patches | 9 ++ ...n_electron_module_via_the_esm_loader.patch | 87 +++++++++++++++++++ spec-main/modules-spec.ts | 12 +++ 3 files changed, 108 insertions(+) create mode 100644 patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch diff --git a/patches/node/.patches b/patches/node/.patches index 22e77d301fb08..588622421ba49 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -45,3 +45,12 @@ json_parse_errors_made_user-friendly.patch build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch build_ensure_native_module_compilation_fails_if_not_using_a_new.patch buffer_fix_atob_input_validation.patch +fix_override_createjob_in_node_platform.patch +src_fix_ssize_t_error_from_nghttp2_h.patch +v8_api_advance_api_deprecation.patch +enable_-wunqualified-std-cast-call.patch +fixup_for_error_declaration_shadows_a_local_variable.patch +fixup_for_wc_98-compat-extra-semi.patch +drop_deserializerequest_move_constructor_for_c_20_compat.patch +fix_parallel_test-v8-stats.patch +fix_expose_the_built-in_electron_module_via_the_esm_loader.patch diff --git a/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch b/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch new file mode 100644 index 0000000000000..e70d970682d46 --- /dev/null +++ b/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Attard +Date: Thu, 6 Oct 2022 04:09:16 -0700 +Subject: fix: expose the built-in electron module via the ESM loader + +This allows usage of `import { app } from 'electron'` and `import('electron')` natively in the browser + non-sandboxed renderer + +diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js +index 5ae0e17dcfb5e24a1a117c33c4d42891686e693f..619fe6cef3b02eb575410225f41d3e7d51f37b93 100644 +--- a/lib/internal/modules/esm/get_format.js ++++ b/lib/internal/modules/esm/get_format.js +@@ -31,6 +31,7 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), { + 'http:': getHttpProtocolModuleFormat, + 'https:': getHttpProtocolModuleFormat, + 'node:'() { return 'builtin'; }, ++ 'electron:'() { return 'commonjs'; }, + }); + + function getDataProtocolModuleFormat(parsed) { +diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js +index fc5dcd6863dc358102a74bd2cc723d54436fae64..97eea17d815967671a2a0fc2a9c95a9bb85947ac 100644 +--- a/lib/internal/modules/esm/resolve.js ++++ b/lib/internal/modules/esm/resolve.js +@@ -883,6 +883,8 @@ function parsePackageName(specifier, base) { + return { packageName, packageSubpath, isScoped }; + } + ++const electronSpecifiers = new SafeSet(['electron', 'electron/main', 'electron/common', 'electron/renderer']); ++ + /** + * @param {string} specifier + * @param {string | URL | undefined} base +@@ -895,6 +897,10 @@ function packageResolve(specifier, base, conditions) { + return new URL('node:' + specifier); + } + ++ if (electronSpecifiers.has(specifier)) { ++ return new URL('electron:electron'); ++ } ++ + const { packageName, packageSubpath, isScoped } = + parsePackageName(specifier, base); + +@@ -1095,7 +1101,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { + + function throwIfUnsupportedURLProtocol(url) { + if (url.protocol !== 'file:' && url.protocol !== 'data:' && +- url.protocol !== 'node:') { ++ url.protocol !== 'node:' && url.protocol !== 'electron:') { + throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url); + } + } +diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js +index 8fb3c96f8dc4c535c3898755f7846ae24d9867c4..bda3ca0797e8f1b1d69295c2276c0f841cae99f2 100644 +--- a/lib/internal/modules/esm/translators.js ++++ b/lib/internal/modules/esm/translators.js +@@ -155,7 +155,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source, + + if (!cjsParse) await initCJSParse(); + const { module, exportNames } = cjsPreparseModuleExports(filename); +- const namesWithDefault = exportNames.has('default') ? ++ const namesWithDefault = filename === 'electron' ? ['default', ...Object.keys(module.exports)] : exportNames.has('default') ? + [...exportNames] : ['default', ...exportNames]; + + return new ModuleWrap(url, undefined, namesWithDefault, function() { +@@ -174,7 +174,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source, + } + } + +- for (const exportName of exportNames) { ++ for (const exportName of namesWithDefault) { + if (!ObjectPrototypeHasOwnProperty(exports, exportName) || + exportName === 'default') + continue; +diff --git a/lib/internal/url.js b/lib/internal/url.js +index 22bff28595f6f5b109ae47c79aa1f5ac463ec6c3..d4eb2e044cc1152f48c92d0503f9216e3aad5f4b 100644 +--- a/lib/internal/url.js ++++ b/lib/internal/url.js +@@ -1432,6 +1432,8 @@ function fileURLToPath(path) { + path = new URL(path); + else if (!isURLInstance(path)) + throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path); ++ if (path.protocol === 'electron:') ++ return 'electron'; + if (path.protocol !== 'file:') + throw new ERR_INVALID_URL_SCHEME('file'); + return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); diff --git a/spec-main/modules-spec.ts b/spec-main/modules-spec.ts index a83797961fcf7..0cebbbeb642d9 100644 --- a/spec-main/modules-spec.ts +++ b/spec-main/modules-spec.ts @@ -183,4 +183,16 @@ describe('modules support', () => { }); }); }); + + describe('esm', () => { + it('can load the built-in "electron" module via ESM import', async () => { + await expect(import('electron')).to.eventually.be.ok(); + }); + + it('the built-in "electron" module loaded via ESM import has the same exports as the CJS module', async () => { + const esmElectron = await import('electron'); + const cjsElectron = require('electron'); + expect(Object.keys(esmElectron)).to.deep.equal(Object.keys(cjsElectron)); + }); + }); }); From 8bbf89531b8b6fd5dbd671d2d7e9126517415ece Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 11 Oct 2022 02:41:19 -0700 Subject: [PATCH 2/3] Update .patches --- patches/node/.patches | 8 -------- 1 file changed, 8 deletions(-) diff --git a/patches/node/.patches b/patches/node/.patches index 588622421ba49..e0bb962af4240 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -45,12 +45,4 @@ json_parse_errors_made_user-friendly.patch build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch build_ensure_native_module_compilation_fails_if_not_using_a_new.patch buffer_fix_atob_input_validation.patch -fix_override_createjob_in_node_platform.patch -src_fix_ssize_t_error_from_nghttp2_h.patch -v8_api_advance_api_deprecation.patch -enable_-wunqualified-std-cast-call.patch -fixup_for_error_declaration_shadows_a_local_variable.patch -fixup_for_wc_98-compat-extra-semi.patch -drop_deserializerequest_move_constructor_for_c_20_compat.patch -fix_parallel_test-v8-stats.patch fix_expose_the_built-in_electron_module_via_the_esm_loader.patch From a11fbacdd084a9d10d65cf51c0ce76bd18c1b4ad Mon Sep 17 00:00:00 2001 From: PatchUp <73610968+patchup[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 09:56:20 +0000 Subject: [PATCH 3/3] chore: update patches --- ...t-in_electron_module_via_the_esm_loader.patch | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch b/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch index e70d970682d46..ca41bd3391169 100644 --- a/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch +++ b/patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch @@ -18,10 +18,10 @@ index 5ae0e17dcfb5e24a1a117c33c4d42891686e693f..619fe6cef3b02eb575410225f41d3e7d function getDataProtocolModuleFormat(parsed) { diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js -index fc5dcd6863dc358102a74bd2cc723d54436fae64..97eea17d815967671a2a0fc2a9c95a9bb85947ac 100644 +index 3576f75f0a40a64dceb7e2649b344b83ebc04b39..314fbb78931eef154a1e47c655e2d4bafe11bac3 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js -@@ -883,6 +883,8 @@ function parsePackageName(specifier, base) { +@@ -888,6 +888,8 @@ function parsePackageName(specifier, base) { return { packageName, packageSubpath, isScoped }; } @@ -30,9 +30,9 @@ index fc5dcd6863dc358102a74bd2cc723d54436fae64..97eea17d815967671a2a0fc2a9c95a9b /** * @param {string} specifier * @param {string | URL | undefined} base -@@ -895,6 +897,10 @@ function packageResolve(specifier, base, conditions) { +@@ -898,6 +900,10 @@ function packageResolve(specifier, base, conditions) { + if (NativeModule.canBeRequiredByUsers(specifier)) return new URL('node:' + specifier); - } + if (electronSpecifiers.has(specifier)) { + return new URL('electron:electron'); @@ -41,7 +41,7 @@ index fc5dcd6863dc358102a74bd2cc723d54436fae64..97eea17d815967671a2a0fc2a9c95a9b const { packageName, packageSubpath, isScoped } = parsePackageName(specifier, base); -@@ -1095,7 +1101,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { +@@ -1099,7 +1105,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { function throwIfUnsupportedURLProtocol(url) { if (url.protocol !== 'file:' && url.protocol !== 'data:' && @@ -51,7 +51,7 @@ index fc5dcd6863dc358102a74bd2cc723d54436fae64..97eea17d815967671a2a0fc2a9c95a9b } } diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js -index 8fb3c96f8dc4c535c3898755f7846ae24d9867c4..bda3ca0797e8f1b1d69295c2276c0f841cae99f2 100644 +index d7f4c7edec63d3ce500955a37c6eac00e3e524fd..b97cac53365b121f8e232f0085ff166511c3dda3 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -155,7 +155,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source, @@ -73,10 +73,10 @@ index 8fb3c96f8dc4c535c3898755f7846ae24d9867c4..bda3ca0797e8f1b1d69295c2276c0f84 exportName === 'default') continue; diff --git a/lib/internal/url.js b/lib/internal/url.js -index 22bff28595f6f5b109ae47c79aa1f5ac463ec6c3..d4eb2e044cc1152f48c92d0503f9216e3aad5f4b 100644 +index 939374a495856cf2b9c573fa98dc1895eee5e143..c37258ac29e8b7558c1f9a2af7ba6bdd0eab1355 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js -@@ -1432,6 +1432,8 @@ function fileURLToPath(path) { +@@ -1418,6 +1418,8 @@ function fileURLToPath(path) { path = new URL(path); else if (!isURLInstance(path)) throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);