feat: promisify executeJavaScript (#17312)
This commit is contained in:
parent
878538f2e8
commit
2e89348541
14 changed files with 164 additions and 100 deletions
|
@ -178,47 +178,25 @@ const webFrameMethods = [
|
|||
'setVisualZoomLevelLimits'
|
||||
]
|
||||
|
||||
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcMainInternal.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, error, result) {
|
||||
if (error == null) {
|
||||
if (typeof callback === 'function') callback(result)
|
||||
resolve(result)
|
||||
} else {
|
||||
reject(errorUtils.deserialize(error))
|
||||
}
|
||||
})
|
||||
this._sendInternal('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
|
||||
})
|
||||
}
|
||||
|
||||
for (const method of webFrameMethods) {
|
||||
WebContents.prototype[method] = function (...args) {
|
||||
ipcMainUtils.invokeInWebContents(this, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
const executeJavaScript = (contents, code, hasUserGesture) => {
|
||||
return ipcMainUtils.invokeInWebContents(contents, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture)
|
||||
}
|
||||
|
||||
// Make sure WebContents::executeJavaScript would run the code only when the
|
||||
// WebContents has been loaded.
|
||||
WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) {
|
||||
const requestId = getNextId()
|
||||
|
||||
if (typeof hasUserGesture === 'function') {
|
||||
// Shift.
|
||||
callback = hasUserGesture
|
||||
hasUserGesture = null
|
||||
}
|
||||
|
||||
if (hasUserGesture == null) {
|
||||
hasUserGesture = false
|
||||
}
|
||||
|
||||
WebContents.prototype.executeJavaScript = function (code, hasUserGesture) {
|
||||
if (this.getURL() && !this.isLoadingMainFrame()) {
|
||||
return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
|
||||
return executeJavaScript(this, code, hasUserGesture)
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.once('did-stop-loading', () => {
|
||||
asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture).then(resolve).catch(reject)
|
||||
executeJavaScript(this, code, hasUserGesture).then(resolve, reject)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -345,6 +323,7 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
|
|||
}
|
||||
|
||||
WebContents.prototype.capturePage = deprecate.promisify(WebContents.prototype.capturePage)
|
||||
WebContents.prototype.executeJavaScript = deprecate.promisify(WebContents.prototype.executeJavaScript)
|
||||
WebContents.prototype.printToPDF = deprecate.promisify(WebContents.prototype.printToPDF)
|
||||
WebContents.prototype.savePage = deprecate.promisify(WebContents.prototype.savePage)
|
||||
|
||||
|
|
|
@ -94,10 +94,12 @@ const deprecate: ElectronInternal.DeprecationUtil = {
|
|||
process.nextTick(() => {
|
||||
cb!.length === 2 ? cb!(null, res) : cb!(res)
|
||||
})
|
||||
return res
|
||||
}, (err: Error) => {
|
||||
process.nextTick(() => {
|
||||
cb!.length === 2 ? cb!(err) : cb!()
|
||||
})
|
||||
throw err
|
||||
})
|
||||
} as T
|
||||
},
|
||||
|
|
|
@ -85,6 +85,15 @@ function getWebFrame (context: Window) {
|
|||
return context ? new WebFrame(context) : null
|
||||
}
|
||||
|
||||
const promisifiedMethods = new Set<string>([
|
||||
'executeJavaScript',
|
||||
'executeJavaScriptInIsolatedWorld'
|
||||
])
|
||||
|
||||
for (const method of promisifiedMethods) {
|
||||
(WebFrame as any).prototype[method] = deprecate.promisify((WebFrame as any).prototype[method])
|
||||
}
|
||||
|
||||
const _webFrame = new WebFrame(window)
|
||||
|
||||
export default _webFrame
|
||||
|
|
|
@ -64,16 +64,14 @@ const getIsRemoteProtocol = function () {
|
|||
* @returns {boolean} Is a CSP with `unsafe-eval` set?
|
||||
*/
|
||||
const isUnsafeEvalEnabled = function () {
|
||||
return new Promise((resolve) => {
|
||||
webFrame.executeJavaScript(`(${(() => {
|
||||
try {
|
||||
new Function('') // eslint-disable-line no-new,no-new-func
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).toString()})()`, false, resolve)
|
||||
})
|
||||
return webFrame.executeJavaScript(`(${(() => {
|
||||
try {
|
||||
new Function('') // eslint-disable-line no-new,no-new-func
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).toString()})()`, false)
|
||||
}
|
||||
|
||||
const moreInformation = `\nFor more information and help, consult
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { webFrame, WebFrame } from 'electron'
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils'
|
||||
import * as errorUtils from '@electron/internal/common/error-utils'
|
||||
|
||||
// All keys of WebFrame that extend Function
|
||||
type WebFrameMethod = {
|
||||
|
@ -19,21 +17,4 @@ export const webFrameInit = () => {
|
|||
// will be caught by "keyof WebFrameMethod" though.
|
||||
return (webFrame[method] as any)(...args)
|
||||
})
|
||||
|
||||
ipcRendererInternal.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (
|
||||
event, requestId: number, method: keyof WebFrameMethod, args: any[]
|
||||
) => {
|
||||
new Promise(resolve =>
|
||||
// The TypeScript compiler cannot handle the sheer number of
|
||||
// call signatures here and simply gives up. Incorrect invocations
|
||||
// will be caught by "keyof WebFrameMethod" though.
|
||||
(webFrame[method] as any)(...args, resolve)
|
||||
).then(result => {
|
||||
return [null, result]
|
||||
}, error => {
|
||||
return [errorUtils.serialize(error)]
|
||||
}).then(responseArgs => {
|
||||
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, ...responseArgs)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue