diff --git a/build/webpack/webpack.config.base.js b/build/webpack/webpack.config.base.js index 2afc874ac1f67..d267344c6757d 100644 --- a/build/webpack/webpack.config.base.js +++ b/build/webpack/webpack.config.base.js @@ -74,7 +74,10 @@ module.exports = ({ global: ['@electron/internal/renderer/webpack-provider', '_global'], Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'], }) - ] : []) + ] : []), + new webpack.ProvidePlugin({ + Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'], + }), ] }) -} \ No newline at end of file +} diff --git a/filenames.auto.gni b/filenames.auto.gni index cf87af39e1163..854d68d43939f 100644 --- a/filenames.auto.gni +++ b/filenames.auto.gni @@ -141,6 +141,7 @@ auto_filenames = { "lib/common/electron-binding-setup.ts", "lib/common/remote/type-utils.ts", "lib/common/web-view-methods.ts", + "lib/common/webpack-globals-provider.ts", "lib/renderer/api/context-bridge.ts", "lib/renderer/api/crash-reporter.js", "lib/renderer/api/desktop-capturer.ts", @@ -188,6 +189,7 @@ auto_filenames = { content_script_bundle_deps = [ "lib/common/electron-binding-setup.ts", + "lib/common/webpack-globals-provider.ts", "lib/content_script/init.js", "lib/renderer/chrome-api.ts", "lib/renderer/extensions/event.ts", @@ -275,6 +277,7 @@ auto_filenames = { "lib/common/remote/type-utils.ts", "lib/common/reset-search-paths.ts", "lib/common/web-view-methods.ts", + "lib/common/webpack-globals-provider.ts", "lib/renderer/ipc-renderer-internal-utils.ts", "lib/renderer/ipc-renderer-internal.ts", "package.json", @@ -297,6 +300,7 @@ auto_filenames = { "lib/common/remote/type-utils.ts", "lib/common/reset-search-paths.ts", "lib/common/web-view-methods.ts", + "lib/common/webpack-globals-provider.ts", "lib/renderer/api/context-bridge.ts", "lib/renderer/api/crash-reporter.js", "lib/renderer/api/desktop-capturer.ts", @@ -345,6 +349,7 @@ auto_filenames = { "lib/common/init.ts", "lib/common/remote/type-utils.ts", "lib/common/reset-search-paths.ts", + "lib/common/webpack-globals-provider.ts", "lib/renderer/api/context-bridge.ts", "lib/renderer/api/crash-reporter.js", "lib/renderer/api/desktop-capturer.ts", diff --git a/lib/common/asar.js b/lib/common/asar.js index 67b7b813f8515..f9313a9158180 100644 --- a/lib/common/asar.js +++ b/lib/common/asar.js @@ -8,6 +8,8 @@ const path = require('path') const util = require('util') + const Promise = global.Promise + const envNoAsar = process.env.ELECTRON_NO_ASAR && process.type !== 'browser' && process.type !== 'renderer' diff --git a/lib/common/webpack-globals-provider.ts b/lib/common/webpack-globals-provider.ts new file mode 100644 index 0000000000000..f7d64270776ae --- /dev/null +++ b/lib/common/webpack-globals-provider.ts @@ -0,0 +1,8 @@ +// Captures original globals into a scope to ensure that userland modifications do +// not impact Electron. Note that users doing: +// +// global.Promise.resolve = myFn +// +// Will mutate this captured one as well and that is OK. + +export const Promise = global.Promise diff --git a/spec/api-remote-spec.js b/spec/api-remote-spec.js index 1231bdb352453..a5f68ff8ee069 100644 --- a/spec/api-remote-spec.js +++ b/spec/api-remote-spec.js @@ -576,4 +576,22 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => { w.loadFile(path.join(fixtures, 'api', 'remote-event-handler.html')) }) }) + + describe('with an overriden global Promise constrctor', () => { + let original + + before(() => { + original = Promise + }) + + it('using a promise based method resolves correctly', async () => { + expect(await remote.getGlobal('returnAPromise')(123)).to.equal(123) + global.Promise = { resolve: () => ({}) } + expect(await remote.getGlobal('returnAPromise')(456)).to.equal(456) + }) + + after(() => { + global.Promise = original + }) + }) }) diff --git a/spec/static/main.js b/spec/static/main.js index d4458e78f3274..bb2315fe5c4b1 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -75,6 +75,7 @@ ipcMain.on('echo', function (event, msg) { }) global.setTimeoutPromisified = util.promisify(setTimeout) +global.returnAPromise = (value) => new Promise((resolve) => setTimeout(() => resolve(value), 100)) global.isCi = !!argv.ci if (global.isCi) {