Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Problem/Bug]: Unable to execute/inject bulk script #4611

Open
Jenifer-TheCoder opened this issue Jun 4, 2024 · 6 comments
Open

[Problem/Bug]: Unable to execute/inject bulk script #4611

Jenifer-TheCoder opened this issue Jun 4, 2024 · 6 comments
Assignees
Labels
bug Something isn't working

Comments

@Jenifer-TheCoder
Copy link

What happened?

I am trying to execute script of 3 different bigger javascript files on webview2 as a string buffer using ExecuteScript function as below:

					webview->ExecuteScript(scriptToInject.c_str(), Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
						[](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT {
							LPCWSTR URL = resultObjectAsJson;
							return S_OK;
						}).Get());

With single line javascript execution, it is all fine. But when I try to execute bigger ones, I get null as return string.
I dont think string buffer limit might be an issue here.

Importance

Blocking. My app's basic functions are not working due to this issue.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

No response

SDK Version

No response

Framework

Win32

Operating System

Windows 10

OS Version

No response

Repro steps

  • Read the bulkier javascript files into stream.
  • Like one file of 8500 lines, others might be 260 & 30 lines.
  • Now try to execute a specific function on the first file to get return value out of it.

Actual Result : You will get null as a string
Expected Result : The Actual return value of a function

Repros in Edge Browser

Yes, issue can be reproduced in the corresponding Edge version

Regression

No, this never worked

Last working version (if regression)

No response

@Jenifer-TheCoder Jenifer-TheCoder added the bug Something isn't working label Jun 4, 2024
@vbryh-msft
Copy link
Contributor

Could you show the smallest example which does not work? Is 30 lines do not work, but 29 lines works?

@Jenifer-TheCoder
Copy link
Author

Ok Let us try to narrow down the problem. I have a simple JS script as below:

std::wstring bulkyScript = LR"( console.log("Bulky script loaded successfully"); function Start() { console.log("Start function called"); return 'Hello, World!'; } )"; std::wstring smallScript1 = LR"(console.log("Small script 1 loaded successfully");)"; std::wstring smallScript2 = LR"(console.log("Small script 2 loaded successfully");)";

I am executing the above using AddScriptToExecuteOnDocumentCreated function:
webView->AddScriptToExecuteOnDocumentCreated(script.c_str(), nullptr);

Now I have a function to execute and get a return value which is already defined in the above executed code.
ExecuteScript function is as below:
void ExecuteScript(ICoreWebView2* webView, const std::wstring& script) { webView->ExecuteScript(script.c_str(), Callback<ICoreWebView2ExecuteScriptCompletedHandler>( [](HRESULT errorCode, LPCWSTR result) -> HRESULT { if (SUCCEEDED(errorCode)) { wprintf(L"Script executed successfully: %s\n", result); } else { wprintf(L"Script execution failed: %08X\n", errorCode); } return S_OK; }).Get()); }
Now trying to execute a Start function as below returns null :
ExecuteScript(webView, L"Start();");

Hope this data is enough, rather than worrying about javascript buffer size let me get a way to execute a function that is already been injected into webview2.

@vbryh-msft
Copy link
Contributor

Could you please try this approach - #4124 (comment) - if it will work for you

@Jenifer-TheCoder
Copy link
Author

@vbryh-msft , thanks for your response. Executing the bulky script on the first go is fine, but in the next script execution I need to get return value . Here I can't get the return value with synchronous call. That is my actual issue here!

@vbryh-msft
Copy link
Contributor

We have ExecuteScriptWithResult API - is it what you are looking for?

@Jenifer-TheCoder
Copy link
Author

Yes that is correct but that is what ExecuteScript with callback should do I suppose. Instead of such huge code with ExecuteScriptWithResult as below:

void ScriptComponent::ExecuteScriptWithResult()
{
    TextInputDialog dialog(
        m_appWindow->GetMainWindow(), L"Execute Script With Result", L"Enter script code:",
        L"Enter the JavaScript code to run in the webview.", L"");
    if (dialog.confirmed)
    {
        wil::com_ptr<ICoreWebView2_21> webView = m_webView.try_query<ICoreWebView2_21>();

        if (!webView)
        {
            MessageBox(
                nullptr, L"Get webview2 failed!", L"ExecuteScriptWithResult Result", MB_OK);
            return;
        }

        // The main interface for excute script, the first param is the string
        // which user want to execute, the second param is the callback to process
        // the result, here use a lamada to the param.
        webView->ExecuteScriptWithResult(
            dialog.input.c_str(),
            // The callback function has two param, the first one is the status of call.s
            // it will always be the S_OK for now, and the second is the result struct.
            Callback<ICoreWebView2ExecuteScriptWithResultCompletedHandler>(
                [this](HRESULT errorCode, ICoreWebView2ExecuteScriptResult* result) -> HRESULT
                {
                    if (errorCode != S_OK || result == nullptr)
                    {
                        MessageBox(
                            nullptr, L"Call interface failed!",
                            L"ExecuteScriptWithResult Result", MB_OK);
                        return S_OK;
                    }
                    else
                    {
                        wil::com_ptr<ICoreWebView2ScriptException> exception;
                        BOOL isSuccess;

                        // User should always invoke the get_Success firstly to get if execute
                        // success.
                        if (result->get_Succeeded(&isSuccess) != S_OK)
                        {
                            MessageBox(
                                nullptr, L"Get execute status failed!",
                                L"ExecuteScriptWithResult Result", MB_OK);
                            return S_OK;
                        }

                        // If execute success, then we can get the raw json data, and try to get
                        // the string.
                        if (isSuccess)
                        {
                            wil::unique_cotaskmem_string rawJsonData;
                            // Get the raw json.
                            if (result->get_ResultAsJson(&rawJsonData) == S_OK)
                            {
                                MessageBox(
                                    nullptr, rawJsonData.get(),
                                    L"ExecuteScriptWithResult Json Result", MB_OK);
                            }
                            else
                            {
                                MessageBox(
                                    nullptr, L"Get raw json data failed",
                                    L"ExecuteScriptWithResult Json Result", MB_OK);
                            }

                            // Get the string, and if the result is not the string type,
                            // it will return the E_INVALIDARG.
                            wil::unique_cotaskmem_string stringData;
                            BOOL isString = FALSE;
                            if (result->TryGetResultAsString(&stringData, &isString) == S_OK &&
                                isString)
                            {
                                MessageBox(
                                    nullptr, stringData.get(),
                                    L"ExecuteScriptWithResult String Result", MB_OK);
                            }
                            else
                            {
                                MessageBox(
                                    nullptr, L"Get string failed",
                                    L"ExecuteScriptWithResult String Result", MB_OK);
                            }
                        }
                        else // If execute failed, then we can get the exception struct to get
                             // the reason of failed.
                        {
                            if (result->get_Exception(&exception) == S_OK)
                            {
                                // Get the exception name, this could return the empty string,
                                // such as `throw 1`.
                                wil::unique_cotaskmem_string exceptionName;
                                if (exception && exception->get_Name(&exceptionName) == S_OK)
                                {
                                    MessageBox(
                                        nullptr, exceptionName.get(),
                                        L"ExecuteScriptWithResult Exception Name", MB_OK);
                                }

                                // Get the exception message, this could return the empty
                                // string, such as `throw 1`.
                                wil::unique_cotaskmem_string exceptionMessage;
                                if (exception &&
                                    exception->get_Message(&exceptionMessage) == S_OK)
                                {
                                    MessageBox(
                                        nullptr, exceptionMessage.get(),
                                        L"ExecuteScriptWithResult Exception Message", MB_OK);
                                }

                                // Get the exception detail, it's a json struct data with all
                                // exception infomation , we can parse it and get the detail
                                // what we need.
                                wil::unique_cotaskmem_string exceptionDetail;
                                if (exception &&
                                    exception->get_ToJson(&exceptionDetail) == S_OK)
                                {
                                    MessageBox(
                                        nullptr, exceptionDetail.get(),
                                        L"ExecuteScriptWithResult Exception Detail", MB_OK);
                                }

                                uint32_t lineNumber = 0;
                                uint32_t columnNumber = 0;
                                if (exception &&
                                    exception->get_LineNumber(&lineNumber) == S_OK &&
                                    exception->get_ColumnNumber(&columnNumber) == S_OK)
                                {
                                    auto exceptionLocationInfo =
                                        L"LineNumber:" + std::to_wstring(lineNumber) +
                                        L", ColumnNumber:" + std::to_wstring(columnNumber);
                                    MessageBox(
                                        nullptr, exceptionLocationInfo.c_str(),
                                        L"ExecuteScriptWithResult Exception Location", MB_OK);
                                }
                            }
                            else
                            {
                                MessageBox(
                                    nullptr, L"Get exception failed",
                                    L"ExecuteScriptWithResult Result", MB_OK);
                            }
                        }
                    }
                    return S_OK;
                })
                .Get());
    }
}

Why can't get we it working with ExecuteScript & callback as below:?

{
        webView->ExecuteScript(script.c_str(), Callback<ICoreWebView2ExecuteScriptCompletedHandler>
( [](HRESULT errorCode, LPCWSTR result) -> HRESULT 
{ if (SUCCEEDED(errorCode))
 { wprintf(L"Script executed successfully: %s\n", result); 
} 
else 
{ wprintf(L"Script execution failed: %08X\n", errorCode);
 }
 return S_OK; }).Get());
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants