Changeset 253950 in webkit


Ignore:
Timestamp:
Dec 30, 2019 12:23:20 PM (4 years ago)
Author:
beidson@apple.com
Message:

Add WKWebView SPI to evaluate a function with arguments
https://bugs.webkit.org/show_bug.cgi?id=205239

Reviewed by Alex Christensen.

Source/WebCore:

Covered by new API tests.

  • Headers.cmake:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/ExceptionDetails.h:
  • bindings/js/RunJavaScriptParameters.h: Added.

(WebCore::RunJavaScriptParameters::RunJavaScriptParameters):
(WebCore::RunJavaScriptParameters::encode const):
(WebCore::RunJavaScriptParameters::decode):

  • bindings/js/ScriptController.cpp:

(WebCore::ScriptController::executeScriptInWorldIgnoringException):
(WebCore::ScriptController::executeScriptInWorld):
(WebCore::ScriptController::callInWorld):
(WebCore::ScriptController::executeUserAgentScriptInWorld):
(WebCore::ScriptController::executeUserAgentScriptInWorldInternal):
(WebCore::ScriptController::executeAsynchronousUserAgentScriptInWorld):

  • bindings/js/ScriptController.h:

XPathGrammar changes completely unrelated to the functionality of this patch,
but because of our poor #include hygiene these were necessary to keep linuxes building.

  • xml/XPathGrammar.cpp:
  • xml/XPathGrammar.y:

Source/WebKit:

  • Shared/API/APISerializedScriptValue.h:
  • UIProcess/API/C/WKPage.cpp:

(WKPageRunJavaScriptInMainFrame):

  • UIProcess/API/Cocoa/APISerializedScriptValueCocoa.mm:

(API::sharedContext):
(API::SerializedScriptValue::deserialize):
(API::SerializedScriptValue::wireBytesFromNSObject):

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView evaluateJavaScript:completionHandler:]):
(validateArgument):
(-[WKWebView _evaluateJavaScript:asAsyncFunction:withArguments:forceUserGesture:completionHandler:]):
(-[WKWebView _callAsyncFunction:withArguments:completionHandler:]):
(-[WKWebView _evaluateJavaScriptWithoutUserGesture:completionHandler:]):
(-[WKWebView _evaluateJavaScript:forceUserGesture:completionHandler:]): Deleted.

  • UIProcess/API/Cocoa/WKWebViewPrivate.h:
  • UIProcess/API/glib/WebKitWebView.cpp:

(webkit_web_view_run_javascript):
(webkit_web_view_run_javascript_in_world):
(resourcesStreamReadCallback):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::runJavaScriptInMainFrame):
(WebKit::WebPageProxy::runJavaScriptInMainFrameScriptWorld):

  • UIProcess/WebPageProxy.h:
  • UIProcess/socket/RemoteInspectorProtocolHandler.cpp:

(WebKit::RemoteInspectorProtocolHandler::runScript):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::runJavaScript):
(WebKit::WebPage::runJavaScriptInMainFrameScriptWorld):
(WebKit::WebPage::runJavaScriptInFrame):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Tools:

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm: Added.

(TestWebKitAPI::TEST):

  • TestWebKitAPI/cocoa/TestWKWebView.h:
  • TestWebKitAPI/cocoa/TestWKWebView.mm:

(-[WKWebView objectByCallingAsyncFunction:withArguments:error:]):

Location:
trunk
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r253949 r253950  
     12019-12-30  Brady Eidson  <beidson@apple.com>
     2
     3        Add WKWebView SPI to evaluate a function with arguments
     4        https://bugs.webkit.org/show_bug.cgi?id=205239
     5
     6        Reviewed by Alex Christensen.
     7
     8        Covered by new API tests.
     9
     10        * Headers.cmake:
     11        * WebCore.xcodeproj/project.pbxproj:
     12       
     13        * bindings/js/ExceptionDetails.h:
     14       
     15        * bindings/js/RunJavaScriptParameters.h: Added.
     16        (WebCore::RunJavaScriptParameters::RunJavaScriptParameters):
     17        (WebCore::RunJavaScriptParameters::encode const):
     18        (WebCore::RunJavaScriptParameters::decode):
     19       
     20        * bindings/js/ScriptController.cpp:
     21        (WebCore::ScriptController::executeScriptInWorldIgnoringException):
     22        (WebCore::ScriptController::executeScriptInWorld):
     23        (WebCore::ScriptController::callInWorld):
     24        (WebCore::ScriptController::executeUserAgentScriptInWorld):
     25        (WebCore::ScriptController::executeUserAgentScriptInWorldInternal):
     26        (WebCore::ScriptController::executeAsynchronousUserAgentScriptInWorld):
     27        * bindings/js/ScriptController.h:
     28       
     29        XPathGrammar changes completely unrelated to the functionality of this patch,
     30        but because of our poor #include hygiene these were necessary to keep linuxes building.
     31        * xml/XPathGrammar.cpp:
     32        * xml/XPathGrammar.y:
     33
    1342019-12-30  Antti Koivisto  <antti@apple.com>
    235
  • trunk/Source/WebCore/Headers.cmake

    r253939 r253950  
    241241    bindings/js/JSWindowProxy.h
    242242    bindings/js/ReadableStreamDefaultController.h
     243    bindings/js/RunJavaScriptParameters.h
    243244    bindings/js/ScriptCachedFrameData.h
    244245    bindings/js/ScriptController.h
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r253939 r253950  
    15341534                51BA4ACB1BBC5BD900DF3D6D /* MemoryIDBBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA4AC91BBC5B9E00DF3D6D /* MemoryIDBBackingStore.h */; };
    15351535                51BA4ACC1BBC5BDD00DF3D6D /* IDBBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA4AC71BBC5AD600DF3D6D /* IDBBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1536                51BA947123AC305300444846 /* RunJavaScriptParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA946F23AC305000444846 /* RunJavaScriptParameters.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15361537                51BCCE301F8F179E006BA0ED /* ServiceWorkerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 517C87101F8EE72E00EB8076 /* ServiceWorkerThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15371538                51BE37E00DAEE00E001085FC /* StorageArea.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BE37DE0DAEE00E001085FC /* StorageArea.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    83378338                51BA4AC81BBC5B9E00DF3D6D /* MemoryIDBBackingStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryIDBBackingStore.cpp; sourceTree = "<group>"; };
    83388339                51BA4AC91BBC5B9E00DF3D6D /* MemoryIDBBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryIDBBackingStore.h; sourceTree = "<group>"; };
     8340                51BA946F23AC305000444846 /* RunJavaScriptParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RunJavaScriptParameters.h; sourceTree = "<group>"; };
    83398341                51BE37DE0DAEE00E001085FC /* StorageArea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageArea.h; sourceTree = "<group>"; };
    83408342                51C0AA380F2AA10A001648C2 /* CachedFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedFrame.h; sourceTree = "<group>"; };
     
    2540625408                                418C395E1C8F0AAB0051C8A3 /* ReadableStreamDefaultController.cpp */,
    2540725409                                418C395F1C8F0AAB0051C8A3 /* ReadableStreamDefaultController.h */,
     25410                                51BA946F23AC305000444846 /* RunJavaScriptParameters.h */,
    2540825411                                41F1D21E0EF35C2A00DA8753 /* ScriptCachedFrameData.cpp */,
    2540925412                                41F1D21D0EF35C2A00DA8753 /* ScriptCachedFrameData.h */,
     
    3213232135                                A79BADA2161E7F3F00C2E652 /* RuleFeature.h in Headers */,
    3213332136                                A79BADA4161E7F3F00C2E652 /* RuleSet.h in Headers */,
     32137                                51BA947123AC305300444846 /* RunJavaScriptParameters.h in Headers */,
    3213432138                                2D76BB821945632400CFD29A /* RunLoopObserver.h in Headers */,
    3213532139                                1A569D1F0D7E2B82007C3983 /* runtime_array.h in Headers */,
  • trunk/Source/WebCore/bindings/js/ExceptionDetails.h

    r251690 r253950  
    3434    int lineNumber { 0 };
    3535    int columnNumber { 0 };
    36     String sourceURL;
     36    // This bizarre explicit initialization of String is because older compilers (like on High Sierra)
     37    // don't properly handle partial initialization lists unless every struct member has an explicit default value.
     38    // Once we stop building on those platforms we can remove this.
     39    String sourceURL { };
    3740};
    3841
  • trunk/Source/WebCore/bindings/js/ScriptController.cpp

    r253654 r253950  
    4848#include "PaymentCoordinator.h"
    4949#include "PluginViewBase.h"
     50#include "RunJavaScriptParameters.h"
    5051#include "RuntimeApplicationChecks.h"
    5152#include "ScriptDisallowedScope.h"
     
    566567JSC::JSValue ScriptController::executeScriptInWorldIgnoringException(DOMWrapperWorld& world, const String& script, bool forceUserGesture)
    567568{
    568     auto result = executeScriptInWorld(world, script, forceUserGesture);
     569    auto result = executeScriptInWorld(world, RunJavaScriptParameters { script, false, WTF::nullopt, forceUserGesture });
    569570    return result ? result.value() : JSC::JSValue { };
    570571}
    571572
    572 ValueOrException ScriptController::executeScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture)
    573 {
    574     UserGestureIndicator gestureIndicator(forceUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt);
    575     ScriptSourceCode sourceCode(script, URL(m_frame.document()->url()), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset()));
     573ValueOrException ScriptController::executeScriptInWorld(DOMWrapperWorld& world, RunJavaScriptParameters&& parameters)
     574{
     575    UserGestureIndicator gestureIndicator(parameters.forceUserGesture == ForceUserGesture::Yes ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt);
    576576
    577577    // FIXME: Instead of returning an empty JSValue, should return an ExceptionDetails.
     
    579579        return { };
    580580
    581     return evaluateInWorld(sourceCode, world);
     581    switch (parameters.runAsAsyncFunction) {
     582    case RunAsAsyncFunction::No: {
     583        ScriptSourceCode sourceCode(parameters.source, URL(m_frame.document()->url()), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset()));
     584        return evaluateInWorld(sourceCode, world);
     585    }
     586    case RunAsAsyncFunction::Yes:
     587        return callInWorld(WTFMove(parameters), world);
     588    default:
     589        RELEASE_ASSERT_NOT_REACHED();
     590    }
     591}
     592
     593ValueOrException ScriptController::callInWorld(RunJavaScriptParameters&& parameters, DOMWrapperWorld& world)
     594{
     595    ASSERT(parameters.runAsAsyncFunction == RunAsAsyncFunction::Yes);
     596    ASSERT(parameters.arguments);
     597
     598    auto& proxy = jsWindowProxy(world);
     599    auto& globalObject = *proxy.window();
     600    MarkedArgumentBuffer markedArguments;
     601    StringBuilder functionStringBuilder;
     602    String errorMessage;
     603
     604    // Build up a new script string that is an async function with arguments, and deserialize those arguments.
     605    functionStringBuilder.append("(function(");
     606    for (auto argument = parameters.arguments->begin(); argument != parameters.arguments->end();) {
     607        functionStringBuilder.append(argument->key);
     608        auto serializedArgument = SerializedScriptValue::createFromWireBytes(WTFMove(argument->value));
     609
     610        auto scope = DECLARE_CATCH_SCOPE(globalObject.vm());
     611        auto jsArgument = serializedArgument->deserialize(globalObject, &globalObject);
     612        if (UNLIKELY(scope.exception())) {
     613            errorMessage = "Unable to deserialize argument to execute asynchronous JavaScript function";
     614            break;
     615        }
     616
     617        markedArguments.append(jsArgument);
     618
     619        ++argument;
     620        if (argument != parameters.arguments->end())
     621            functionStringBuilder.append(',');
     622    }
     623
     624    if (!errorMessage.isEmpty())
     625        return makeUnexpected(ExceptionDetails { errorMessage });
     626
     627    functionStringBuilder.append("){", parameters.source, "})");
     628
     629    auto sourceCode = ScriptSourceCode { functionStringBuilder.toString(), URL(m_frame.document()->url()), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset()) };
     630    const auto& jsSourceCode = sourceCode.jsSourceCode();
     631
     632    String sourceURL = jsSourceCode.provider()->url();
     633    const String* savedSourceURL = m_sourceURL;
     634    m_sourceURL = &sourceURL;
     635
     636    Ref<Frame> protector(m_frame);
     637
     638    InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine(), sourceCode.startColumn());
     639
     640    NakedPtr<JSC::Exception> evaluationException;
     641    Optional<ExceptionDetails> optionalDetails;
     642    JSValue returnValue;
     643    do {
     644        JSValue functionObject = JSExecState::profiledEvaluate(&globalObject, JSC::ProfilingReason::Other, jsSourceCode, &proxy, evaluationException);
     645
     646        if (evaluationException)
     647            break;
     648
     649        if (!functionObject || !functionObject.isFunction(world.vm())) {
     650            optionalDetails = { { "Unable to create JavaScript async function to call"_s } };
     651            break;
     652        }
     653
     654        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=205562
     655        // Getting CallData/CallType shouldn't be required to call into JS.
     656        CallData callData;
     657        CallType callType = getCallData(world.vm(), functionObject, callData);
     658        if (callType == CallType::None) {
     659            optionalDetails = { { "Unable to prepare JavaScript async function to be called"_s } };
     660            break;
     661        }
     662
     663        returnValue = JSExecState::profiledCall(&globalObject, JSC::ProfilingReason::Other, functionObject, callType, callData, &proxy, markedArguments, evaluationException);
     664    } while (false);
     665
     666    InspectorInstrumentation::didEvaluateScript(m_frame);
     667
     668    if (evaluationException && !optionalDetails) {
     669        ExceptionDetails details;
     670        reportException(&globalObject, evaluationException, sourceCode.cachedScript(), &details);
     671        optionalDetails = WTFMove(details);
     672    }
     673
     674    m_sourceURL = savedSourceURL;
     675
     676    if (optionalDetails)
     677        return makeUnexpected(*optionalDetails);
     678    return returnValue;
    582679}
    583680
     
    589686ValueOrException ScriptController::executeUserAgentScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture)
    590687{
     688    return executeUserAgentScriptInWorldInternal(world, { script, false, WTF::nullopt, forceUserGesture });
     689}
     690
     691ValueOrException ScriptController::executeUserAgentScriptInWorldInternal(DOMWrapperWorld& world, RunJavaScriptParameters&& parameters)
     692{
    591693    auto& document = *m_frame.document();
    592694    if (!shouldAllowUserAgentScripts(document))
    593         return makeUnexpected(ExceptionDetails { "Unable to run user agent scripts in this document for security reasons"_s, 0, 0, { } });
     695        return makeUnexpected(ExceptionDetails { "Unable to run user agent scripts in this document for security reasons"_s });
    594696
    595697    document.setHasEvaluatedUserAgentScripts();
    596     return executeScriptInWorld(world, script, forceUserGesture);
     698    return executeScriptInWorld(world, WTFMove(parameters));
     699}
     700
     701void ScriptController::executeAsynchronousUserAgentScriptInWorld(DOMWrapperWorld& world, RunJavaScriptParameters&& parameters, ResolveFunction&& resolveFunction)
     702{
     703    auto result = executeUserAgentScriptInWorldInternal(world, WTFMove(parameters));
     704
     705    // FIXME: If the result is a thenable, install the fulfill/reject handlers instead of resolving now.
     706
     707    resolveFunction(result);
    597708}
    598709
  • trunk/Source/WebCore/bindings/js/ScriptController.h

    r253654 r253950  
    2424#include "FrameLoaderTypes.h"
    2525#include "JSWindowProxy.h"
     26#include "SerializedScriptValue.h"
    2627#include "WindowProxy.h"
    2728#include <JavaScriptCore/JSBase.h>
     
    6465class SecurityOrigin;
    6566class Widget;
     67
     68enum class RunAsAsyncFunction : bool;
     69
    6670struct ExceptionDetails;
     71struct RunJavaScriptParameters;
    6772
    6873enum ReasonForCallingCanExecuteScripts {
     
    9297    static void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&);
    9398
     99    using ResolveFunction = CompletionHandler<void(ValueOrException)>;
     100
    94101    WEBCORE_EXPORT JSC::JSValue executeScriptIgnoringException(const String& script, bool forceUserGesture = false);
    95102    JSC::JSValue executeScriptInWorldIgnoringException(DOMWrapperWorld&, const String& script, bool forceUserGesture = false);
    96     ValueOrException executeScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture = false);
    97103    WEBCORE_EXPORT JSC::JSValue executeUserAgentScriptInWorldIgnoringException(DOMWrapperWorld&, const String& script, bool forceUserGesture);
    98104    WEBCORE_EXPORT ValueOrException executeUserAgentScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture);
     105    WEBCORE_EXPORT void executeAsynchronousUserAgentScriptInWorld(DOMWrapperWorld&, RunJavaScriptParameters&&, ResolveFunction&&);
     106    JSC::JSValue evaluateIgnoringException(const ScriptSourceCode&);
     107    JSC::JSValue evaluateInWorldIgnoringException(const ScriptSourceCode&, DOMWrapperWorld&);
    99108
    100109    bool shouldAllowUserAgentScripts(Document&) const;
     
    106115    // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
    107116    static void initializeThreading();
    108 
    109     JSC::JSValue evaluateIgnoringException(const ScriptSourceCode&);
    110     JSC::JSValue evaluateInWorldIgnoringException(const ScriptSourceCode&, DOMWrapperWorld&);
    111     ValueOrException evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&);
    112117
    113118    void loadModuleScriptInWorld(LoadableModuleScript&, const String& moduleName, Ref<ModuleFetchParameters>&&, DOMWrapperWorld&);
     
    172177
    173178private:
     179    ValueOrException executeUserAgentScriptInWorldInternal(DOMWrapperWorld&, RunJavaScriptParameters&&);
     180    ValueOrException executeScriptInWorld(DOMWrapperWorld&, RunJavaScriptParameters&&);
     181    ValueOrException evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&);
     182    ValueOrException callInWorld(RunJavaScriptParameters&&, DOMWrapperWorld&);
     183   
    174184    void setupModuleScriptHandlers(LoadableModuleScript&, JSC::JSInternalPromise&, DOMWrapperWorld&);
    175185
  • trunk/Source/WebCore/xml/XPathGrammar.cpp

    r235935 r253950  
    19731973    {
    19741974        (yyvsp[(3) - (3)].locationPath)->setAbsolute();
    1975         (yyval.expression) = new Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath)));
     1975        (yyval.expression) = new XPath::Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath)));
    19761976    ;}
    19771977    break;
     
    19821982        (yyvsp[(3) - (3)].locationPath)->prependStep(std::unique_ptr<Step>((yyvsp[(2) - (3)].step)));
    19831983        (yyvsp[(3) - (3)].locationPath)->setAbsolute();
    1984         (yyval.expression) = new Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath)));
     1984        (yyval.expression) = new XPath::Path(std::unique_ptr<Expression>((yyvsp[(1) - (3)].expression)), std::unique_ptr<LocationPath>((yyvsp[(3) - (3)].locationPath)));
    19851985    ;}
    19861986    break;
  • trunk/Source/WebCore/xml/XPathGrammar.y

    r209883 r253950  
    402402    {
    403403        $3->setAbsolute();
    404         $$ = new Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
     404        $$ = new XPath::Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
    405405    }
    406406    |
     
    409409        $3->prependStep(std::unique_ptr<Step>($2));
    410410        $3->setAbsolute();
    411         $$ = new Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
     411        $$ = new XPath::Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
    412412    }
    413413    ;
  • trunk/Source/WebKit/ChangeLog

    r253941 r253950  
     12019-12-30  Brady Eidson  <beidson@apple.com>
     2
     3        Add WKWebView SPI to evaluate a function with arguments
     4        https://bugs.webkit.org/show_bug.cgi?id=205239
     5
     6        Reviewed by Alex Christensen.
     7
     8        * Shared/API/APISerializedScriptValue.h:
     9
     10        * UIProcess/API/C/WKPage.cpp:
     11        (WKPageRunJavaScriptInMainFrame):
     12
     13        * UIProcess/API/Cocoa/APISerializedScriptValueCocoa.mm:
     14        (API::sharedContext):
     15        (API::SerializedScriptValue::deserialize):
     16        (API::SerializedScriptValue::wireBytesFromNSObject):
     17
     18        * UIProcess/API/Cocoa/WKWebView.mm:
     19        (-[WKWebView evaluateJavaScript:completionHandler:]):
     20        (validateArgument):
     21        (-[WKWebView _evaluateJavaScript:asAsyncFunction:withArguments:forceUserGesture:completionHandler:]):
     22        (-[WKWebView _callAsyncFunction:withArguments:completionHandler:]):
     23        (-[WKWebView _evaluateJavaScriptWithoutUserGesture:completionHandler:]):
     24        (-[WKWebView _evaluateJavaScript:forceUserGesture:completionHandler:]): Deleted.
     25        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
     26
     27        * UIProcess/API/glib/WebKitWebView.cpp:
     28        (webkit_web_view_run_javascript):
     29        (webkit_web_view_run_javascript_in_world):
     30        (resourcesStreamReadCallback):
     31
     32        * UIProcess/WebPageProxy.cpp:
     33        (WebKit::WebPageProxy::runJavaScriptInMainFrame):
     34        (WebKit::WebPageProxy::runJavaScriptInMainFrameScriptWorld):
     35        * UIProcess/WebPageProxy.h:
     36
     37        * UIProcess/socket/RemoteInspectorProtocolHandler.cpp:
     38        (WebKit::RemoteInspectorProtocolHandler::runScript):
     39
     40        * WebProcess/WebPage/WebPage.cpp:
     41        (WebKit::WebPage::runJavaScript):
     42        (WebKit::WebPage::runJavaScriptInMainFrameScriptWorld):
     43        (WebKit::WebPage::runJavaScriptInFrame):
     44        * WebProcess/WebPage/WebPage.h:
     45        * WebProcess/WebPage/WebPage.messages.in:
     46
    1472019-12-29  Peng Liu  <peng.liu6@apple.com>
    248
  • trunk/Source/WebKit/Shared/API/APISerializedScriptValue.h

    r225278 r253950  
    6262#if PLATFORM(COCOA) && defined(__OBJC__)
    6363    static id deserialize(WebCore::SerializedScriptValue&, JSValueRef* exception);
     64    static Optional<Vector<uint8_t>> wireBytesFromNSObject(id);
    6465#endif
    6566
  • trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp

    r253519 r253950  
    24732473void WKPageRunJavaScriptInMainFrame(WKPageRef pageRef, WKStringRef scriptRef, void* context, WKPageRunJavaScriptFunction callback)
    24742474{
    2475     toImpl(pageRef)->runJavaScriptInMainFrame(toImpl(scriptRef)->string(), true, [context, callback](API::SerializedScriptValue* returnValue, Optional<WebCore::ExceptionDetails>, CallbackBase::Error error) {
     2475    toImpl(pageRef)->runJavaScriptInMainFrame({ toImpl(scriptRef)->string(), false, WTF::nullopt, true }, [context, callback](API::SerializedScriptValue* returnValue, Optional<WebCore::ExceptionDetails>, CallbackBase::Error error) {
    24762476        callback(toAPI(returnValue), (error != CallbackBase::Error::None) ? toAPI(API::Error::create().ptr()) : 0, context);
    24772477    });
  • trunk/Source/WebKit/UIProcess/API/Cocoa/APISerializedScriptValueCocoa.mm

    r242339 r253950  
    2727#include "APISerializedScriptValue.h"
    2828
     29#import <JavaScriptCore/APICast.h>
    2930#import <JavaScriptCore/JSContext.h>
     31#import <JavaScriptCore/JSGlobalObjectInlines.h>
    3032#import <JavaScriptCore/JSValue.h>
    3133#import <wtf/NeverDestroyed.h>
     
    6062};
    6163
     64static SharedJSContext& sharedContext()
     65{
     66    static NeverDestroyed<SharedJSContext> sharedContext;
     67    return sharedContext.get();
     68}
     69
    6270id SerializedScriptValue::deserialize(WebCore::SerializedScriptValue& serializedScriptValue, JSValueRef* exception)
    6371{
    6472    ASSERT(RunLoop::isMain());
    65     static NeverDestroyed<SharedJSContext> sharedContext;
    66     JSContext* context = sharedContext.get().ensureContext();
     73    JSContext* context = sharedContext().ensureContext();
    6774
    6875    JSValueRef valueRef = serializedScriptValue.deserialize([context JSGlobalContextRef], exception);
     
    7481}
    7582
     83Optional<Vector<uint8_t>> SerializedScriptValue::wireBytesFromNSObject(id object)
     84{
     85    ASSERT(RunLoop::isMain());
     86    JSContext* context = sharedContext().ensureContext();
     87    JSValue *value = [JSValue valueWithObject:object inContext:context];
     88    if (!value)
     89        return WTF::nullopt;
     90
     91    auto globalObject = toJS([context JSGlobalContextRef]);
     92    ASSERT(globalObject);
     93    JSC::JSLockHolder lock(globalObject);
     94
     95    auto coreValue = WebCore::SerializedScriptValue::create(*globalObject, toJS(globalObject, [value JSValueRef]));
     96    return coreValue->toWireBytes();
     97}
     98
    7699} // API
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r253733 r253950  
    823823- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
    824824{
    825     [self _evaluateJavaScript:javaScriptString forceUserGesture:YES completionHandler:completionHandler];
    826 }
    827 
    828 - (void)_evaluateJavaScript:(NSString *)javaScriptString forceUserGesture:(BOOL)forceUserGesture completionHandler:(void (^)(id, NSError *))completionHandler
     825    [self _evaluateJavaScript:javaScriptString asAsyncFunction:NO withArguments:nil forceUserGesture:YES completionHandler:completionHandler];
     826}
     827
     828static bool validateArgument(id argument)
     829{
     830    if ([argument isKindOfClass:[NSString class]] || [argument isKindOfClass:[NSNumber class]] || [argument isKindOfClass:[NSDate class]] || [argument isKindOfClass:[NSNull class]])
     831        return true;
     832
     833    if ([argument isKindOfClass:[NSArray class]]) {
     834        __block BOOL valid = true;
     835
     836        [argument enumerateObjectsUsingBlock:^(id object, NSUInteger, BOOL *stop) {
     837            if (!validateArgument(object)) {
     838                valid = false;
     839                *stop = YES;
     840            }
     841        }];
     842
     843        return valid;
     844    }
     845
     846    if ([argument isKindOfClass:[NSDictionary class]]) {
     847        __block bool valid = true;
     848
     849        [argument enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
     850            if (!validateArgument(key) || !validateArgument(value)) {
     851                valid = false;
     852                *stop = YES;
     853            }
     854        }];
     855
     856        return valid;
     857    }
     858
     859    return false;
     860}
     861
     862- (void)_evaluateJavaScript:(NSString *)javaScriptString asAsyncFunction:(BOOL)asAsyncFunction withArguments:(NSDictionary<NSString *, id> *)arguments forceUserGesture:(BOOL)forceUserGesture completionHandler:(void (^)(id, NSError *))completionHandler
    829863{
    830864    auto handler = adoptNS([completionHandler copy]);
    831865
    832     _page->runJavaScriptInMainFrame(javaScriptString, forceUserGesture, [handler](API::SerializedScriptValue* serializedScriptValue, Optional<WebCore::ExceptionDetails> details, WebKit::ScriptValueCallback::Error errorCode) {
     866    Optional<WebCore::ArgumentWireBytesMap> argumentsMap;
     867    if (asAsyncFunction)
     868        argumentsMap = WebCore::ArgumentWireBytesMap { };
     869    NSString *errorMessage = nil;
     870
     871    for (id key in arguments) {
     872        id value = [arguments objectForKey:key];
     873        if (!validateArgument(value)) {
     874            errorMessage = @"Function argument values must be one of the following types, or contain only the following types: NSString, NSNumber, NSDate, NSArray, and NSDictionary";
     875            break;
     876        }
     877   
     878        auto wireBytes = API::SerializedScriptValue::wireBytesFromNSObject(value);
     879        // Since we've validated the input dictionary above, we should never fail to serialize it into wire bytes.
     880        ASSERT(wireBytes);
     881        argumentsMap->set(key, *wireBytes);
     882    }
     883
     884    if (errorMessage) {
     885        RetainPtr<NSMutableDictionary> userInfo = adoptNS([[NSMutableDictionary alloc] init]);
     886
     887        [userInfo setObject:localizedDescriptionForErrorCode(WKErrorJavaScriptExceptionOccurred) forKey:NSLocalizedDescriptionKey];
     888        [userInfo setObject:errorMessage forKey:_WKJavaScriptExceptionMessageErrorKey];
     889
     890        auto error = adoptNS([[NSError alloc] initWithDomain:WKErrorDomain code:WKErrorJavaScriptExceptionOccurred userInfo:userInfo.get()]);
     891        dispatch_async(dispatch_get_main_queue(), [handler, error] {
     892            auto rawHandler = (void (^)(id, NSError *))handler.get();
     893            rawHandler(nil, error.get());
     894        });
     895
     896        return;
     897    }
     898
     899    _page->runJavaScriptInMainFrame(WebCore::RunJavaScriptParameters { javaScriptString, !!asAsyncFunction, WTFMove(argumentsMap), !!forceUserGesture }, [handler](API::SerializedScriptValue* serializedScriptValue, Optional<WebCore::ExceptionDetails> details, WebKit::ScriptValueCallback::Error errorCode) {
    833900        if (!handler)
    834901            return;
     
    19241991}
    19251992
     1993- (void)_callAsyncFunction:(NSString *)javaScriptString withArguments:(NSDictionary<NSString *, id> *)arguments completionHandler:(void (^)(id, NSError *error))completionHandler
     1994{
     1995    [self _evaluateJavaScript:javaScriptString asAsyncFunction:YES withArguments:arguments forceUserGesture:YES completionHandler:completionHandler];
     1996}
     1997
    19261998- (NSData *)_sessionStateData
    19271999{
     
    20662138- (void)_evaluateJavaScriptWithoutUserGesture:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
    20672139{
    2068     [self _evaluateJavaScript:javaScriptString forceUserGesture:NO completionHandler:completionHandler];
     2140    [self _evaluateJavaScript:javaScriptString asAsyncFunction:NO withArguments:nil forceUserGesture:NO completionHandler:completionHandler];
    20692141}
    20702142
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h

    r253733 r253950  
    316316
    317317- (void)_takePDFSnapshotWithConfiguration:(WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(NSData *pdfSnapshotData, NSError *error))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     318
     319- (void)_callAsyncFunction:(NSString *)javaScriptString withArguments:(NSDictionary<NSString *, id> *)arguments completionHandler:(void (^)(id, NSError *error))completionHandler;
     320
    318321@end
    319322
  • trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp

    r253881 r253950  
    36373637
    36383638    GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
    3639     getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(script), true, [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, Optional<ExceptionDetails> details, WebKit::CallbackBase::Error) {
     3639    getPage(webView).runJavaScriptInMainFrame({ String::fromUTF8(script), false, WTF::nullopt, true }, [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, Optional<ExceptionDetails> details, WebKit::CallbackBase::Error) {
    36403640        ExceptionDetails exceptionDetails;
    36413641        if (details)
     
    37383738
    37393739    GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
    3740     getPage(webView).runJavaScriptInMainFrameScriptWorld(String::fromUTF8(script), true, String::fromUTF8(worldName), [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, Optional<ExceptionDetails> details, WebKit::CallbackBase::Error) {
     3740    getPage(webView).runJavaScriptInMainFrameScriptWorld({ String::fromUTF8(script), false, WTF::nullopt, true }, String::fromUTF8(worldName), [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, Optional<ExceptionDetails> details, WebKit::CallbackBase::Error) {
    37413741        ExceptionDetails exceptionDetails;
    37423742        if (details)
     
    37803780    WebKitWebView* webView = WEBKIT_WEB_VIEW(g_task_get_source_object(task.get()));
    37813781    gpointer outputStreamData = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(object));
    3782     getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(reinterpret_cast<const gchar*>(outputStreamData)), true,
     3782    getPage(webView).runJavaScriptInMainFrame({ String::fromUTF8(reinterpret_cast<const gchar*>(outputStreamData)), false, WTF::nullopt, true},
    37833783        [task](API::SerializedScriptValue* serializedScriptValue, Optional<ExceptionDetails> details, WebKit::CallbackBase::Error) {
    37843784            ExceptionDetails exceptionDetails;
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r253881 r253950  
    38503850}
    38513851
    3852 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction)
    3853 {
    3854     runJavaScriptInMainFrameScriptWorld(script, forceUserGesture, WTF::nullopt, WTFMove(callbackFunction));
    3855 }
    3856 
    3857 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const Optional<String>& worldName, WTF::Function<void(API::SerializedScriptValue*, Optional<ExceptionDetails>, CallbackBase::Error)>&& callbackFunction)
     3852void WebPageProxy::runJavaScriptInMainFrame(RunJavaScriptParameters&& parameters, WTF::Function<void (API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction)
     3853{
     3854    runJavaScriptInMainFrameScriptWorld(WTFMove(parameters), WTF::nullopt, WTFMove(callbackFunction));
     3855}
     3856
     3857void WebPageProxy::runJavaScriptInMainFrameScriptWorld(RunJavaScriptParameters&& parameters, const Optional<String>& worldName, WTF::Function<void(API::SerializedScriptValue*, Optional<ExceptionDetails>, CallbackBase::Error)>&& callbackFunction)
    38583858{
    38593859    // For backward-compatibility support running script in a WebView which has not done any loads yets.
     
    38663866
    38673867    auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivity("WebPageProxy::runJavaScriptInMainFrameScriptWorld"_s));
    3868     send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID));
     3868    send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(parameters, worldName, callbackID));
    38693869}
    38703870
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r253881 r253950  
    9393#include <WebCore/PointerID.h>
    9494#include <WebCore/RegistrableDomain.h>
     95#include <WebCore/RunJavaScriptParameters.h>
    9596#include <WebCore/ScrollTypes.h>
    9697#include <WebCore/SearchPopupMenu.h>
     
    10631064    void getSourceForFrame(WebFrameProxy*, WTF::Function<void (const String&, CallbackBase::Error)>&&);
    10641065    void getWebArchiveOfFrame(WebFrameProxy*, Function<void (API::Data*, CallbackBase::Error)>&&);
    1065     void runJavaScriptInMainFrame(const String&, bool, WTF::Function<void (API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction);
    1066     void runJavaScriptInMainFrameScriptWorld(const String&, bool, const Optional<String>& worldName, WTF::Function<void(API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction);
     1066    void runJavaScriptInMainFrame(WebCore::RunJavaScriptParameters&&, WTF::Function<void (API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction);
     1067    void runJavaScriptInMainFrameScriptWorld(WebCore::RunJavaScriptParameters&&, const Optional<String>& worldName, WTF::Function<void(API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction);
    10671068    // For sub frames.
    10681069    void runJavaScriptInFrame(WebCore::FrameIdentifier, const String& script, bool forceUserGesture, WTF::Function<void(API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails>, CallbackBase::Error)>&& callbackFunction);
  • trunk/Source/WebKit/UIProcess/socket/RemoteInspectorProtocolHandler.cpp

    r253868 r253950  
    127127void RemoteInspectorProtocolHandler::runScript(const String& script)
    128128{
    129     m_page.runJavaScriptInMainFrame(script, false,
     129    m_page.runJavaScriptInMainFrame({ script, false, WTF::nullopt, false },
    130130        [](API::SerializedScriptValue*, Optional<WebCore::ExceptionDetails> exceptionDetails, CallbackBase::Error) {
    131131            if (exceptionDetails)
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r253881 r253950  
    215215#include <WebCore/ResourceRequest.h>
    216216#include <WebCore/ResourceResponse.h>
     217#include <WebCore/RunJavaScriptParameters.h>
    217218#include <WebCore/RuntimeEnabledFeatures.h>
    218219#include <WebCore/SWClientConnection.h>
     
    33533354}
    33543355
    3355 void WebPage::runJavaScript(WebFrame* frame, const String& script, bool forceUserGesture, const Optional<String>& worldName, CallbackID callbackID)
     3356void WebPage::runJavaScript(WebFrame* frame, RunJavaScriptParameters&& parameters, const Optional<String>& worldName, CallbackID callbackID)
    33563357{
    33573358    // NOTE: We need to be careful when running scripts that the objects we depend on don't
    33583359    // disappear during script execution.
    33593360
    3360     JSLockHolder lock(commonVM());
    3361     ValueOrException result;
    3362     RefPtr<SerializedScriptValue> serializedResultValue;
    3363 
    33643361    auto* world = worldName ? InjectedBundleScriptWorld::find(worldName.value()) : &InjectedBundleScriptWorld::normalWorld();
    3365     if (frame && frame->coreFrame() && world) {
    3366         result = frame->coreFrame()->script().executeUserAgentScriptInWorld(world->coreWorld(), script, forceUserGesture);
     3362    if (!frame || !frame->coreFrame() || !world) {
     3363        send(Messages::WebPageProxy::ScriptValueCallback({ }, ExceptionDetails { "Unable to execute JavaScript: Page is in invalid state"_s }, callbackID));
     3364        return;
     3365    }
     3366
     3367    auto resolveFunction = [protectedThis = makeRef(*this), this, world = makeRef(*world), frame = makeRef(*frame), callbackID](ValueOrException result) {
     3368        RefPtr<SerializedScriptValue> serializedResultValue;
    33673369        if (result) {
    3368             serializedResultValue = SerializedScriptValue::create(frame->jsContextForWorld(world),
     3370            serializedResultValue = SerializedScriptValue::create(frame->jsContextForWorld(world.ptr()),
    33693371                toRef(frame->coreFrame()->script().globalObject(world->coreWorld()), result.value()), nullptr);
    33703372        }
    3371     }
    3372 
    3373     IPC::DataReference dataReference;
    3374     if (serializedResultValue)
    3375         dataReference = serializedResultValue->data();
    3376 
    3377     Optional<ExceptionDetails> details;
    3378     if (!result)
    3379         details = result.error();
    3380 
    3381     send(Messages::WebPageProxy::ScriptValueCallback(dataReference, details, callbackID));
    3382 }
    3383 
    3384 void WebPage::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const Optional<String>& worldName, CallbackID callbackID)
    3385 {
    3386     runJavaScript(mainWebFrame(), script, forceUserGesture, worldName, callbackID);
     3373
     3374        IPC::DataReference dataReference;
     3375        if (serializedResultValue)
     3376            dataReference = serializedResultValue->data();
     3377
     3378        Optional<ExceptionDetails> details;
     3379        if (!result)
     3380            details = result.error();
     3381
     3382        send(Messages::WebPageProxy::ScriptValueCallback(dataReference, details, callbackID));
     3383    };
     3384
     3385    JSLockHolder lock(commonVM());
     3386    frame->coreFrame()->script().executeAsynchronousUserAgentScriptInWorld(world->coreWorld(), WTFMove(parameters), WTFMove(resolveFunction));
     3387}
     3388
     3389void WebPage::runJavaScriptInMainFrameScriptWorld(RunJavaScriptParameters&& parameters, const Optional<String>& worldName, CallbackID callbackID)
     3390{
     3391    runJavaScript(mainWebFrame(), WTFMove(parameters), worldName, callbackID);
    33873392}
    33883393
     
    33913396    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
    33923397    ASSERT(mainWebFrame() != frame);
    3393     runJavaScript(frame, script, forceUserGesture, WTF::nullopt, callbackID);
     3398    runJavaScript(frame, { script, false, WTF::nullopt, forceUserGesture }, WTF::nullopt, callbackID);
    33943399}
    33953400
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r253881 r253950  
    198198struct KeypressCommand;
    199199struct PromisedAttachmentInfo;
     200struct RunJavaScriptParameters;
    200201struct TextCheckingResult;
    201202struct ViewportArguments;
     
    14361437    void getSourceForFrame(WebCore::FrameIdentifier, CallbackID);
    14371438    void getWebArchiveOfFrame(WebCore::FrameIdentifier, CallbackID);
    1438     void runJavaScript(WebFrame*, const String&, bool forceUserGesture, const Optional<String>& worldName, CallbackID);
    1439     void runJavaScriptInMainFrameScriptWorld(const String&, bool forceUserGesture, const Optional<String>& worldName, CallbackID);
     1439    void runJavaScript(WebFrame*, WebCore::RunJavaScriptParameters&&, const Optional<String>& worldName, CallbackID);
     1440    void runJavaScriptInMainFrameScriptWorld(WebCore::RunJavaScriptParameters&&, const Optional<String>& worldName, CallbackID);
    14401441    void runJavaScriptInFrame(WebCore::FrameIdentifier, const String&, bool forceUserGesture, CallbackID);
    14411442    void forceRepaint(CallbackID);
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r253881 r253950  
    205205    GetSourceForFrame(WebCore::FrameIdentifier frameID, WebKit::CallbackID callbackID)
    206206    GetWebArchiveOfFrame(WebCore::FrameIdentifier frameID, WebKit::CallbackID callbackID)
    207     RunJavaScriptInMainFrameScriptWorld(String script, bool forceUserGesture, Optional<String> worldName, WebKit::CallbackID callbackID)
     207    RunJavaScriptInMainFrameScriptWorld(struct WebCore::RunJavaScriptParameters parameters, Optional<String> worldName, WebKit::CallbackID callbackID)
    208208    RunJavaScriptInFrame(WebCore::FrameIdentifier frameID, String script, bool forceUserGesture, WebKit::CallbackID callbackID)
    209209    ForceRepaint(WebKit::CallbackID callbackID)
  • trunk/Tools/ChangeLog

    r253947 r253950  
     12019-12-30  Brady Eidson  <beidson@apple.com>
     2
     3        Add WKWebView SPI to evaluate a function with arguments
     4        https://bugs.webkit.org/show_bug.cgi?id=205239
     5
     6        Reviewed by Alex Christensen.
     7
     8        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     9        * TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm: Added.
     10        (TestWebKitAPI::TEST):
     11        * TestWebKitAPI/cocoa/TestWKWebView.h:
     12        * TestWebKitAPI/cocoa/TestWKWebView.mm:
     13        (-[WKWebView objectByCallingAsyncFunction:withArguments:error:]):
     14
    1152019-12-30  Carlos Alberto Lopez Perez  <clopez@igalia.com>
    216
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r253811 r253950  
    291291                51B1EE961C80FAEF0064FB98 /* IndexedDBPersistence-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51B1EE941C80FADD0064FB98 /* IndexedDBPersistence-1.html */; };
    292292                51B1EE971C80FAEF0064FB98 /* IndexedDBPersistence-2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51B1EE951C80FADD0064FB98 /* IndexedDBPersistence-2.html */; };
     293                51B40D9E23AC962400E05241 /* AsyncFunction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51B40D9D23AC960E00E05241 /* AsyncFunction.mm */; };
    293294                51BCEE4E1C84F53B0042C82E /* IndexedDBMultiProcess-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51BCEE4C1C84F52C0042C82E /* IndexedDBMultiProcess-1.html */; };
    294295                51BCEE4F1C84F53B0042C82E /* IndexedDBMultiProcess-2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51BCEE4D1C84F52C0042C82E /* IndexedDBMultiProcess-2.html */; };
     
    18421843                51B1EE941C80FADD0064FB98 /* IndexedDBPersistence-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBPersistence-1.html"; sourceTree = "<group>"; };
    18431844                51B1EE951C80FADD0064FB98 /* IndexedDBPersistence-2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBPersistence-2.html"; sourceTree = "<group>"; };
     1845                51B40D9D23AC960E00E05241 /* AsyncFunction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AsyncFunction.mm; sourceTree = "<group>"; };
    18441846                51B454EB1B4E236B0085EAA6 /* WebViewCloseInsideDidFinishLoadForFrame.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewCloseInsideDidFinishLoadForFrame.mm; sourceTree = "<group>"; };
    18451847                51BCEE491C84F4AF0042C82E /* IndexedDBMultiProcess.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBMultiProcess.mm; sourceTree = "<group>"; };
     
    28302832                                A1798B8122431D65000764BD /* ApplePay.mm */,
    28312833                                63F668201F97C3AA0032EE51 /* ApplicationManifest.mm */,
     2834                                51B40D9D23AC960E00E05241 /* AsyncFunction.mm */,
    28322835                                834138C6203261B900F26960 /* AsyncPolicyForNavigationResponse.mm */,
    28332836                                3760C4F0211249AF00233ACC /* AttrStyle.mm */,
     
    45374540                                63F668221F97F7F90032EE51 /* ApplicationManifest.mm in Sources */,
    45384541                                6354F4D11F7C3AB500D89DF3 /* ApplicationManifestParser.cpp in Sources */,
     4542                                51B40D9E23AC962400E05241 /* AsyncFunction.mm in Sources */,
    45394543                                834138C7203261CA00F26960 /* AsyncPolicyForNavigationResponse.mm in Sources */,
    45404544                                7CCE7EB41A411A7E00447C4C /* AttributedString.mm in Sources */,
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h

    r252458 r253950  
    6464- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script;
    6565- (id)objectByEvaluatingJavaScript:(NSString *)script;
     66- (id)objectByCallingAsyncFunction:(NSString *)script withArguments:(NSDictionary *)arguments error:(NSError **)errorOut;
    6667- (unsigned)waitUntilClientWidthIs:(unsigned)expectedClientWidth;
    6768@end
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

    r252458 r253950  
    179179}
    180180
     181- (id)objectByCallingAsyncFunction:(NSString *)script withArguments:(NSDictionary *)arguments error:(NSError **)errorOut
     182{
     183    bool isWaitingForJavaScript = false;
     184    if (errorOut)
     185        *errorOut = nil;
     186
     187    RetainPtr<id> evalResult;
     188    [self _callAsyncFunction:script withArguments:arguments completionHandler:[&] (id result, NSError *error) {
     189        evalResult = result;
     190        if (errorOut)
     191            *errorOut = [error retain];
     192        isWaitingForJavaScript = true;
     193    }];
     194    TestWebKitAPI::Util::run(&isWaitingForJavaScript);
     195
     196    if (errorOut)
     197        [*errorOut autorelease];
     198
     199    return evalResult.autorelease();
     200}
     201
    181202- (NSString *)stringByEvaluatingJavaScript:(NSString *)script
    182203{
Note: See TracChangeset for help on using the changeset viewer.