Skip to content

Commit b1ec4d6

Browse files
authored
Create ExecuteScriptWithResult
1 parent cec01da commit b1ec4d6

File tree

1 file changed

+268
-0
lines changed

1 file changed

+268
-0
lines changed

specs/ExecuteScriptWithResult

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# Background
2+
Since the current ExecuteStrip interface is a little shabby, it is necessary
3+
to provide a new interface to let the user get more infomation, and easier to use.
4+
The new interface will provide the exception infomation if the script execute
5+
failed, and provide a new method to try to get the string to resolve the problem
6+
that the old interface is not friendly to the string return type.
7+
8+
In this document we describe the updated API. We'd appreciate your feedback.
9+
10+
# Description
11+
We propose extending `CoreWebView2` to provide an `ExecuteScriptWithResult`
12+
method. The method will return a struct to manage the execute result, which can
13+
get the raw result and string if execute success, and can get exception when
14+
execute failed.
15+
16+
# Examples
17+
The following code snippets demonstrate how the ExecuteScriptWithResult can be used:
18+
## Win32 C++
19+
``` cpp
20+
void ScriptComponent::ExecuteScriptWithResult(LPCWSTR script)
21+
{
22+
wil::com_ptr<ICoreWebView2Staging2> webview2 =
23+
m_webView.try_query<ICoreWebView2Staging2>();
24+
25+
// The main interface for excute script, the first param is the string
26+
// which user want to execute, the second param is the callback to process
27+
// the result, here use a lamada to the param.
28+
webview2->ExecuteScriptWithResult(
29+
script,
30+
// The callback function has two param, the first one is the status of call.
31+
// it will always be the S_OK for now, and the second is the result struct.
32+
Callback<ICoreWebView2StagingExecuteScriptWithResultCompletedHandler>(
33+
[this](
34+
HRESULT errorCode
35+
ICoreWebView2StagingExecuteScriptResult* result) -> HRESULT
36+
{
37+
if (errorCode != S_OK || result == nullptr)
38+
{
39+
MessageBox(nullptr, L"Call interface failed!", L"ExecuteScript Result", MB_OK);
40+
return S_OK;
41+
}
42+
else
43+
{
44+
wil::com_ptr<ICoreWebView2StagingExecuteScriptException> exception;
45+
BOOL is_success;
46+
47+
// User should always invoke the get_IsSuccess firstly to get the execution status.
48+
if (result->get_IsSuccess(&is_success) != S_OK)
49+
{
50+
MessageBox(nullptr, L"Get execute status failed!", L"ExecuteScript Result", MB_OK);
51+
return S_OK;
52+
}
53+
54+
// If execute success, then we can get the raw json data, and try to get the string.
55+
if (is_success)
56+
{
57+
wil::unique_cotaskmem_string rawJsonData;
58+
// Get the raw json.
59+
if (result->get_ResultAsJson(&rawJsonData) == S_OK)
60+
{
61+
MessageBox(
62+
nullptr, rawJsonData.get(), L"ExecuteScript Result", MB_OK);
63+
}
64+
else
65+
{
66+
MessageBox(
67+
nullptr, L"Get raw json data failed", L"ExecuteScript Result", MB_OK);
68+
}
69+
70+
// Get the string, and if the result is not the string type,
71+
// it will return the E_INVALIDARG.
72+
wil::unique_cotaskmem_string stringData;
73+
if (result->TryGetResultAsString(&stringData) == S_OK) {
74+
MessageBox(
75+
nullptr, stringData.get(), L"ExecuteScript Result", MB_OK);
76+
}
77+
else
78+
{
79+
MessageBox(
80+
nullptr, L"Get string failed", L"ExecuteScript Result", MB_OK);
81+
}
82+
}
83+
else // If execute failed, then we can get the exception struct to get the reason of failed.
84+
{
85+
if (result->get_Exception(&exception) == S_OK)
86+
{
87+
// Get the exception name, this could return the empty string, such as `throw 1`.
88+
wil::unique_cotaskmem_string exceptionName;
89+
if (exception && exception->get_Name(&exceptionName) == S_OK)
90+
{
91+
MessageBox(
92+
nullptr, exceptionName.get(), L"ExecuteScript Result", MB_OK);
93+
}
94+
95+
// Get the exception message, this could return the empty string, such as `throw 1`.
96+
wil::unique_cotaskmem_string exceptionMessage;
97+
if (exception && exception->get_Message(&exceptionMessage) == S_OK)
98+
{
99+
MessageBox(
100+
nullptr, exceptionMessage.get(), L"ExecuteScript Result", MB_OK);
101+
}
102+
103+
// Get the exception detail, it's a json struct data with all exception infomation
104+
// , we can parse it and get the detail what we need.
105+
wil::unique_cotaskmem_string exceptionDetail;
106+
if (exception && exception->get_Detail(&exceptionDetail) == S_OK)
107+
{
108+
MessageBox(
109+
nullptr, exceptionDetail.get(), L"ExecuteScript Result", MB_OK);
110+
}
111+
}
112+
else
113+
{
114+
MessageBox(
115+
nullptr, L"Get exception failed", L"ExecuteScript Result", MB_OK);
116+
}
117+
}
118+
119+
}
120+
}
121+
)
122+
)
123+
}
124+
125+
```
126+
## .NET and WinRT
127+
128+
```c#
129+
void ExecuteScriptWithResultAsync(String script)
130+
{
131+
var environment = webView2Control.CoreWebView2.Environment;
132+
CoreWebView2ExecuteScriptResult result = await ExecuteScriptWithResultAsync(script);
133+
134+
bool isSuccess = result.IsSuccess;
135+
if (isSuccess)
136+
{
137+
Debug.WriteLine($"execute script success.");
138+
139+
Debug.WriteLine($"json result received: {result.ResultAsJson}");
140+
try
141+
{
142+
string stringResult = result.TryGetResultAsString();
143+
Debug.WriteLine($"get string result success: {stringResult}");
144+
}
145+
catch (ArgumentException)
146+
{
147+
Debug.WriteLine($"Non-string message received");
148+
}
149+
}
150+
else
151+
{
152+
Debug.WriteLine($"execute script failed.");
153+
CoreWebView2ExecuteScriptException exception = result.Exception;
154+
Debug.WriteLine($"exception name: {exception.Name}");
155+
Debug.WriteLine($"exception message: {exception.Message}");
156+
Debug.WriteLine($"exception Detail: {exception.Detail}");
157+
}
158+
}
159+
```
160+
161+
# API Details
162+
## Win32 C++
163+
```c++
164+
/// This is the exception struct when ExecuteScriptWithResult return false, user can
165+
/// use get_Exception to get it.
166+
[uuid(82F22B72-1B22-403E-A0B9-A8816C9C8E45), object, pointer_default(unique)]
167+
interface ICoreWebView2StagingExecuteScriptException : IUnknown {
168+
169+
/// This will return the exception className, it would be got from the
170+
/// `result.exceptionDetail.exception.className` in json result, this
171+
/// could be empty if the exception doesn't have the specified element,
172+
/// such as user active throw an exception like `throw "abc"`.
173+
[propget] HRESULT Name([out, retval] LPWSTR* value);
174+
175+
/// This will return the exception message, it would be got from the
176+
/// `result.exceptionDetail.exception.description` in json result, this
177+
/// could be empty if the exception doesn't have the specified element,
178+
/// such as user active throw an exception like `throw "abc"`.
179+
[propget] HRESULT Message([out, retval] LPWSTR* value);
180+
181+
/// This will return the exception detail, it's a json struct with complete information for
182+
/// exception, if get_Name and get_Exception is not enough, user can use this interface and
183+
/// get what they want.
184+
[propget] HRESULT Detail([out, retval] LPWSTR* detail);
185+
}
186+
187+
/// This is the result for ExecuteScriptWithResult.
188+
[uuid(D2C59C5C-AD36-4CF4-87CF-2F5359F6D4CB), object, pointer_default(unique)]
189+
interface ICoreWebView2StagingExecuteScriptResult : IUnknown {
190+
191+
/// This property is true if ExecuteScriptWithResult successfully executed script with
192+
/// no unhandled exceptions and the result is available in the ResultAsJson property
193+
/// or via the TryGetResultAsString method.
194+
/// If it is false then the script execution had an unhandled exception which you
195+
/// can get via the Exception property.
196+
[propget] HRESULT IsSuccess([out, retval] BOOL* value);
197+
198+
/// If IsSuccess return true, then this interface will return the raw json data for user
199+
/// var the jsonResult, otherwise return E_INVALIDARG.
200+
[propget] HRESULT ResultAsJson([out, retval] LPWSTR* jsonResult);
201+
202+
/// If IsSuccess return true, this interface can let user try to get string result when
203+
/// the result type is string, otherwise return E_INVALIDARG.
204+
HRESULT TryGetResultAsString([out, retval] LPWSTR* stringResult);
205+
206+
/// If IsSuccess return failed, user can use this interface to get exception to handle,
207+
/// otherwise return E_INVALIDARG.
208+
[propget] HRESULT Exception(
209+
[out, retval] ICoreWebView2StagingExecuteScriptException** exception);
210+
}
211+
212+
/// This is the callback for ExecuteScriptWithResult
213+
[uuid(CECDD25B-E6E8-4A4E-B890-BBF95932564F), object, pointer_default(unique)]
214+
interface ICoreWebView2StagingExecuteScriptWithResultCompletedHandler : IUnknown {
215+
216+
/// Provides the event args for the execute result.
217+
HRESULT Invoke(
218+
[in] HRESULT errorCode,
219+
[in] ICoreWebView2StagingExecuteScriptResult* result);
220+
}
221+
222+
/// This is the interface for getting string and exception with ExecuteScriptWithResult
223+
[uuid(67E0B57B-1AC7-4395-9793-5E4EF9C4B7D9), object, pointer_default(unique)]
224+
interface ICoreWebView2Staging2 : IUnknown {
225+
226+
/// New execute javascript for user can get the string result and can get exception
227+
/// if execution fails.
228+
HRESULT ExecuteScriptWithResult(
229+
[in] LPCWSTR javaScript,
230+
[in] ICoreWebView2StagingExecuteScriptWithResultCompletedHandler* handler);
231+
}
232+
```
233+
234+
## .NET and WinRT
235+
```c#
236+
namespace Microsoft.Web.WebView2.Core
237+
{
238+
runtimeclass CoreWebView2;
239+
runtimeclass CoreWebView2ExecuteScriptResult;
240+
runtimeclass CoreWebView2ExecuteScriptException;
241+
242+
runtimeclass CoreWebView2
243+
{
244+
Windows.Foundation.IAsyncOperation<CoreWebView2ExecuteScriptResult>
245+
ExecuteScriptWithResultAsync(String javaScript);
246+
}
247+
248+
runtimeclass CoreWebView2ExecuteScriptResult
249+
{
250+
bool IsSuccess { get; };
251+
252+
String ResultAsJson { get; };
253+
254+
String TryGetResultAsString();
255+
}
256+
257+
runtimeclass CoreWebView2ExecuteScriptException
258+
{
259+
String Name { get; };
260+
261+
String Message { get; };
262+
263+
String Detail { get; };
264+
}
265+
}
266+
```
267+
268+

0 commit comments

Comments
 (0)