Browse Source

fix: capture the promise global to avoid userland mutation (#20925)

Samuel Attard 5 years ago
parent
commit
267821831c

+ 5 - 2
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'],
+      }),
     ]
   })
-}
+}

+ 5 - 0
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",

+ 2 - 0
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'

+ 8 - 0
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

+ 18 - 0
spec/api-remote-spec.js

@@ -517,4 +517,22 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
       const arr = new RUint8Array()
     })
   })
+
+  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
+    })
+  })
 })

+ 1 - 0
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))
 
 process.removeAllListeners('uncaughtException')
 process.on('uncaughtException', function (error) {