fix: promise support with webFrameMain.executeJavaScript (#35292)
* fix: promise support with webFrameMain.executeJavaScript * chore: reject when result is an error
This commit is contained in:
		
					parent
					
						
							
								8e4a168a13
							
						
					
				
			
			
				commit
				
					
						43182bf030
					
				
			
		
					 2 changed files with 58 additions and 12 deletions
				
			
		|  | @ -11,8 +11,9 @@ | ||||||
| 
 | 
 | ||||||
| #include "base/logging.h" | #include "base/logging.h" | ||||||
| #include "base/no_destructor.h" | #include "base/no_destructor.h" | ||||||
| #include "content/browser/renderer_host/frame_tree_node.h"  // nogncheck
 | #include "content/browser/renderer_host/render_frame_host_impl.h"  // nogncheck
 | ||||||
| #include "content/public/browser/render_frame_host.h" | #include "content/public/browser/render_frame_host.h" | ||||||
|  | #include "content/public/common/isolated_world_ids.h" | ||||||
| #include "electron/shell/common/api/api.mojom.h" | #include "electron/shell/common/api/api.mojom.h" | ||||||
| #include "gin/object_template_builder.h" | #include "gin/object_template_builder.h" | ||||||
| #include "services/service_manager/public/cpp/interface_provider.h" | #include "services/service_manager/public/cpp/interface_provider.h" | ||||||
|  | @ -141,17 +142,24 @@ v8::Local<v8::Promise> WebFrameMain::ExecuteJavaScript( | ||||||
|     return handle; |     return handle; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (user_gesture) { |   static_cast<content::RenderFrameHostImpl*>(render_frame_) | ||||||
|     auto* ftn = content::FrameTreeNode::From(render_frame_); |       ->ExecuteJavaScriptForTests( | ||||||
|     ftn->UpdateUserActivationState( |           code, user_gesture, true /* resolve_promises */, | ||||||
|         blink::mojom::UserActivationUpdateType::kNotifyActivation, |           content::ISOLATED_WORLD_ID_GLOBAL, | ||||||
|         blink::mojom::UserActivationNotificationType::kTest); |           base::BindOnce( | ||||||
|   } |               [](gin_helper::Promise<base::Value> promise, | ||||||
| 
 |                  blink::mojom::JavaScriptExecutionResultType type, | ||||||
|   render_frame_->ExecuteJavaScriptForTests( |                  base::Value value) { | ||||||
|       code, base::BindOnce([](gin_helper::Promise<base::Value> promise, |                 if (type == | ||||||
|                               base::Value value) { promise.Resolve(value); }, |                     blink::mojom::JavaScriptExecutionResultType::kSuccess) { | ||||||
|                            std::move(promise))); |                   promise.Resolve(value); | ||||||
|  |                 } else { | ||||||
|  |                   v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); | ||||||
|  |                   v8::HandleScope scope(isolate); | ||||||
|  |                   promise.Reject(gin::ConvertToV8(isolate, value)); | ||||||
|  |                 } | ||||||
|  |               }, | ||||||
|  |               std::move(promise))); | ||||||
| 
 | 
 | ||||||
|   return handle; |   return handle; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -163,6 +163,44 @@ describe('webFrameMain module', () => { | ||||||
|       expect(await getUrl(webFrame.frames[0])).to.equal(fileUrl('frame-with-frame.html')); |       expect(await getUrl(webFrame.frames[0])).to.equal(fileUrl('frame-with-frame.html')); | ||||||
|       expect(await getUrl(webFrame.frames[0].frames[0])).to.equal(fileUrl('frame.html')); |       expect(await getUrl(webFrame.frames[0].frames[0])).to.equal(fileUrl('frame.html')); | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     it('can resolve promise', async () => { | ||||||
|  |       const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } }); | ||||||
|  |       await w.loadFile(path.join(subframesPath, 'frame.html')); | ||||||
|  |       const webFrame = w.webContents.mainFrame; | ||||||
|  |       const p = () => webFrame.executeJavaScript('new Promise(resolve => setTimeout(resolve(42), 2000));'); | ||||||
|  |       const result = await p(); | ||||||
|  |       expect(result).to.equal(42); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('can reject with error', async () => { | ||||||
|  |       const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } }); | ||||||
|  |       await w.loadFile(path.join(subframesPath, 'frame.html')); | ||||||
|  |       const webFrame = w.webContents.mainFrame; | ||||||
|  |       const p = () => webFrame.executeJavaScript('new Promise((r,e) => setTimeout(e("error!"), 500));'); | ||||||
|  |       await expect(p()).to.be.eventually.rejectedWith('error!'); | ||||||
|  |       const errorTypes = new Set([ | ||||||
|  |         Error, | ||||||
|  |         ReferenceError, | ||||||
|  |         EvalError, | ||||||
|  |         RangeError, | ||||||
|  |         SyntaxError, | ||||||
|  |         TypeError, | ||||||
|  |         URIError | ||||||
|  |       ]); | ||||||
|  |       for (const error of errorTypes) { | ||||||
|  |         await expect(webFrame.executeJavaScript(`Promise.reject(new ${error.name}("Wamp-wamp"))`)) | ||||||
|  |           .to.eventually.be.rejectedWith(/Error/); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('can reject when script execution fails', async () => { | ||||||
|  |       const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } }); | ||||||
|  |       await w.loadFile(path.join(subframesPath, 'frame.html')); | ||||||
|  |       const webFrame = w.webContents.mainFrame; | ||||||
|  |       const p = () => webFrame.executeJavaScript('console.log(test)'); | ||||||
|  |       await expect(p()).to.be.eventually.rejectedWith(/ReferenceError/); | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   describe('WebFrame.reload', () => { |   describe('WebFrame.reload', () => { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Robo
				Robo