Refactor duplicate code for calling into media controls
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Nov 2018 23:45:43 +0000 (23:45 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Nov 2018 23:45:43 +0000 (23:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192040
<rdar://problem/46278931>

Reviewed by Youenn Fablet.

No new tests, no functional change.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::setupAndCallJS):
(WebCore::HTMLMediaElement::updateCaptionContainer):
(WebCore::HTMLMediaElement::configureTextTrackDisplay):
(WebCore::HTMLMediaElement::ensureMediaControlsInjectedScript):
(WebCore::HTMLMediaElement::setControllerJSProperty):
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
(WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
(WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
* html/HTMLMediaElement.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238582 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h

index 839d809..cdf3ad2 100644 (file)
@@ -1,3 +1,24 @@
+2018-11-27  Eric Carlson  <eric.carlson@apple.com>
+
+        Refactor duplicate code for calling into media controls
+        https://bugs.webkit.org/show_bug.cgi?id=192040
+        <rdar://problem/46278931>
+
+        Reviewed by Youenn Fablet.
+
+        No new tests, no functional change.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::setupAndCallJS):
+        (WebCore::HTMLMediaElement::updateCaptionContainer):
+        (WebCore::HTMLMediaElement::configureTextTrackDisplay):
+        (WebCore::HTMLMediaElement::ensureMediaControlsInjectedScript):
+        (WebCore::HTMLMediaElement::setControllerJSProperty):
+        (WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
+        (WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
+        (WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
+        * html/HTMLMediaElement.h:
+
 2018-11-27  Simon Fraser  <simon.fraser@apple.com>
 
         Momentum scrolling ends at the wrong place when a scrolling overflow element has a non-zero border
index 79e8eb9..f6c24b3 100644 (file)
@@ -4355,18 +4355,32 @@ void HTMLMediaElement::ensureMediaControlsShadowRoot()
     m_creatingControls = false;
 }
 
+bool HTMLMediaElement::setupAndCallJS(const JSSetupFunction& task)
+{
+    Page* page = document().page();
+    if (!page)
+        return false;
+
+    auto pendingActivity = makePendingActivity(*this);
+    auto& world = ensureIsolatedWorld();
+    auto& scriptController = document().frame()->script();
+    auto* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
+    auto& vm = globalObject->vm();
+    JSC::JSLockHolder lock(vm);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    auto* exec = globalObject->globalExec();
+
+    RETURN_IF_EXCEPTION(scope, false);
+
+    return task(*globalObject, *exec, scriptController, world);
+}
+
 void HTMLMediaElement::updateCaptionContainer()
 {
 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
     if (m_haveSetUpCaptionContainer)
         return;
 
-    Page* page = document().page();
-    if (!page)
-        return;
-
-    DOMWrapperWorld& world = ensureIsolatedWorld();
-
     if (!ensureMediaControlsInjectedScript())
         return;
 
@@ -4375,40 +4389,40 @@ void HTMLMediaElement::updateCaptionContainer()
     if (!m_mediaControlsHost)
         m_mediaControlsHost = MediaControlsHost::create(this);
 
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::VM& vm = globalObject->vm();
-    JSC::JSLockHolder lock(vm);
-    auto scope = DECLARE_CATCH_SCOPE(vm);
-    JSC::ExecState* exec = globalObject->globalExec();
+    setupAndCallJS([this](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController&, DOMWrapperWorld&) {
+        auto& vm = globalObject.vm();
+        auto scope = DECLARE_CATCH_SCOPE(vm);
+        auto controllerValue = controllerJSValue(exec, globalObject, *this);
+        auto* controllerObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, controllerValue);
+        if (!controllerObject)
+            return false;
 
-    JSC::JSValue controllerValue = controllerJSValue(*exec, *globalObject, *this);
-    JSC::JSObject* controllerObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, controllerValue);
-    if (!controllerObject)
-        return;
+        // The media controls script must provide a method on the Controller object with the following details.
+        // Name: updateCaptionContainer
+        // Parameters:
+        //     None
+        // Return value:
+        //     None
+        auto methodValue = controllerObject->get(&exec, JSC::Identifier::fromString(&exec, "updateCaptionContainer"));
+        auto* methodObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, methodValue);
+        if (!methodObject)
+            return false;
 
-    // The media controls script must provide a method on the Controller object with the following details.
-    // Name: updateCaptionContainer
-    // Parameters:
-    //     None
-    // Return value:
-    //     None
-    JSC::JSValue methodValue = controllerObject->get(exec, JSC::Identifier::fromString(exec, "updateCaptionContainer"));
-    JSC::JSObject* methodObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, methodValue);
-    if (!methodObject)
-        return;
+        JSC::CallData callData;
+        auto callType = methodObject->methodTable(vm)->getCallData(methodObject, callData);
+        if (callType == JSC::CallType::None)
+            return false;
 
-    JSC::CallData callData;
-    JSC::CallType callType = methodObject->methodTable(vm)->getCallData(methodObject, callData);
-    if (callType == JSC::CallType::None)
-        return;
+        JSC::MarkedArgumentBuffer noArguments;
+        ASSERT(!noArguments.hasOverflowed());
+        JSC::call(&exec, methodObject, callType, callData, controllerObject, noArguments);
+        scope.clearException();
+
+        m_haveSetUpCaptionContainer = true;
 
-    JSC::MarkedArgumentBuffer noArguments;
-    ASSERT(!noArguments.hasOverflowed());
-    JSC::call(exec, methodObject, callType, callData, controllerObject, noArguments);
-    scope.clearException();
+        return true;
+    });
 
-    m_haveSetUpCaptionContainer = true;
 #endif
 }
 
@@ -6491,6 +6505,7 @@ void HTMLMediaElement::configureMediaControls()
 #if ENABLE(VIDEO_TRACK)
 void HTMLMediaElement::configureTextTrackDisplay(TextTrackVisibilityCheckType checkType)
 {
+    ALWAYS_LOG(LOGIDENTIFIER);
     ASSERT(m_textTracks);
 
     if (m_processingPreferenceChange)
@@ -7185,6 +7200,7 @@ DOMWrapperWorld& HTMLMediaElement::ensureIsolatedWorld()
 bool HTMLMediaElement::ensureMediaControlsInjectedScript()
 {
     DEBUG_LOG(LOGIDENTIFIER);
+
     Page* page = document().page();
     if (!page)
         return false;
@@ -7193,31 +7209,28 @@ bool HTMLMediaElement::ensureMediaControlsInjectedScript()
     if (!mediaControlsScript.length())
         return false;
 
-    DOMWrapperWorld& world = ensureIsolatedWorld();
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::VM& vm = globalObject->vm();
-    JSC::JSLockHolder lock(vm);
-    auto scope = DECLARE_CATCH_SCOPE(vm);
-    JSC::ExecState* exec = globalObject->globalExec();
+    return setupAndCallJS([mediaControlsScript](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController& scriptController, DOMWrapperWorld& world) {
+        auto& vm = globalObject.vm();
+        auto scope = DECLARE_CATCH_SCOPE(vm);
 
-    JSC::JSValue functionValue = globalObject->get(exec, JSC::Identifier::fromString(exec, "createControls"));
-    if (functionValue.isFunction(vm))
-        return true;
+        auto functionValue = globalObject.get(&exec, JSC::Identifier::fromString(&exec, "createControls"));
+        if (functionValue.isFunction(vm))
+            return true;
 
 #ifndef NDEBUG
-    // Setting a scriptURL allows the source to be debuggable in the inspector.
-    URL scriptURL = URL({ }, "mediaControlsScript"_s);
+        // Setting a scriptURL allows the source to be debuggable in the inspector.
+        URL scriptURL = URL({ }, "mediaControlsScript"_s);
 #else
-    URL scriptURL;
+        URL scriptURL;
 #endif
-    scriptController.evaluateInWorld(ScriptSourceCode(mediaControlsScript, scriptURL), world);
-    if (UNLIKELY(scope.exception())) {
-        scope.clearException();
-        return false;
-    }
+        scriptController.evaluateInWorld(ScriptSourceCode(mediaControlsScript, scriptURL), world);
+        if (UNLIKELY(scope.exception())) {
+            scope.clearException();
+            return false;
+        }
 
-    return true;
+        return true;
+    });
 }
 
 void HTMLMediaElement::updatePageScaleFactorJSProperty()
@@ -7241,107 +7254,99 @@ void HTMLMediaElement::updateUsesLTRUserInterfaceLayoutDirectionJSProperty()
 
 void HTMLMediaElement::setControllerJSProperty(const char* propertyName, JSC::JSValue propertyValue)
 {
-    DOMWrapperWorld& world = ensureIsolatedWorld();
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::ExecState* exec = globalObject->globalExec();
-    JSC::VM& vm = exec->vm();
-    JSC::JSLockHolder lock(vm);
+    setupAndCallJS([this, propertyName, propertyValue](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController&, DOMWrapperWorld&) {
+        auto& vm = globalObject.vm();
+        auto controllerValue = controllerJSValue(exec, globalObject, *this);
+        if (controllerValue.isNull())
+            return false;
 
-    JSC::JSValue controllerValue = controllerJSValue(*exec, *globalObject, *this);
-    if (controllerValue.isNull())
-        return;
+        JSC::PutPropertySlot propertySlot(controllerValue);
+        auto* controllerObject = controllerValue.toObject(&exec);
+        if (!controllerObject)
+            return false;
 
-    JSC::PutPropertySlot propertySlot(controllerValue);
-    JSC::JSObject* controllerObject = controllerValue.toObject(exec);
-    if (!controllerObject)
-        return;
+        controllerObject->methodTable(vm)->put(controllerObject, &exec, JSC::Identifier::fromString(&exec, propertyName), propertyValue, propertySlot);
 
-    controllerObject->methodTable(vm)->put(controllerObject, exec, JSC::Identifier::fromString(exec, propertyName), propertyValue, propertySlot);
+        return true;
+    });
 }
 
 void HTMLMediaElement::didAddUserAgentShadowRoot(ShadowRoot& root)
 {
     DEBUG_LOG(LOGIDENTIFIER);
 
-    Page* page = document().page();
-    if (!page)
-        return;
-
-    DOMWrapperWorld& world = ensureIsolatedWorld();
-
     if (!ensureMediaControlsInjectedScript())
         return;
 
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::VM& vm = globalObject->vm();
-    JSC::JSLockHolder lock(vm);
-    auto scope = DECLARE_CATCH_SCOPE(vm);
-    JSC::ExecState* exec = globalObject->globalExec();
+    setupAndCallJS([this, &root](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController&, DOMWrapperWorld&) {
+        auto& vm = globalObject.vm();
+        auto scope = DECLARE_CATCH_SCOPE(vm);
 
-    // The media controls script must provide a method with the following details.
-    // Name: createControls
-    // Parameters:
-    //     1. The ShadowRoot element that will hold the controls.
-    //     2. This object (and HTMLMediaElement).
-    //     3. The MediaControlsHost object.
-    // Return value:
-    //     A reference to the created media controller instance.
+        // The media controls script must provide a method with the following details.
+        // Name: createControls
+        // Parameters:
+        //     1. The ShadowRoot element that will hold the controls.
+        //     2. This object (and HTMLMediaElement).
+        //     3. The MediaControlsHost object.
+        // Return value:
+        //     A reference to the created media controller instance.
 
-    JSC::JSValue functionValue = globalObject->get(exec, JSC::Identifier::fromString(exec, "createControls"));
-    if (functionValue.isUndefinedOrNull())
-        return;
+        auto functionValue = globalObject.get(&exec, JSC::Identifier::fromString(&exec, "createControls"));
+        if (functionValue.isUndefinedOrNull())
+            return false;
 
-    if (!m_mediaControlsHost)
-        m_mediaControlsHost = MediaControlsHost::create(this);
+        if (!m_mediaControlsHost)
+            m_mediaControlsHost = MediaControlsHost::create(this);
 
-    auto mediaJSWrapper = toJS(exec, globalObject, *this);
-    auto mediaControlsHostJSWrapper = toJS(exec, globalObject, *m_mediaControlsHost);
+        auto mediaJSWrapper = toJS(&exec, &globalObject, *this);
+        auto mediaControlsHostJSWrapper = toJS(&exec, &globalObject, *m_mediaControlsHost);
 
-    JSC::MarkedArgumentBuffer argList;
-    argList.append(toJS(exec, globalObject, root));
-    argList.append(mediaJSWrapper);
-    argList.append(mediaControlsHostJSWrapper);
-    ASSERT(!argList.hasOverflowed());
+        JSC::MarkedArgumentBuffer argList;
+        argList.append(toJS(&exec, &globalObject, root));
+        argList.append(mediaJSWrapper);
+        argList.append(mediaControlsHostJSWrapper);
+        ASSERT(!argList.hasOverflowed());
 
-    JSC::JSObject* function = functionValue.toObject(exec);
-    scope.assertNoException();
-    JSC::CallData callData;
-    JSC::CallType callType = function->methodTable(vm)->getCallData(function, callData);
-    if (callType == JSC::CallType::None)
-        return;
+        auto* function = functionValue.toObject(&exec);
+        scope.assertNoException();
+        JSC::CallData callData;
+        auto callType = function->methodTable(vm)->getCallData(function, callData);
+        if (callType == JSC::CallType::None)
+            return false;
 
-    JSC::JSValue controllerValue = JSC::call(exec, function, callType, callData, globalObject, argList);
-    scope.clearException();
-    JSC::JSObject* controllerObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, controllerValue);
-    if (!controllerObject)
-        return;
+        auto controllerValue = JSC::call(&exec, function, callType, callData, &globalObject, argList);
+        scope.clearException();
+        auto* controllerObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, controllerValue);
+        if (!controllerObject)
+            return false;
 
-    // Connect the Media, MediaControllerHost, and Controller so the GC knows about their relationship
-    JSC::JSObject* mediaJSWrapperObject = mediaJSWrapper.toObject(exec);
-    scope.assertNoException();
-    JSC::Identifier controlsHost = JSC::Identifier::fromString(&exec->vm(), "controlsHost");
+        // Connect the Media, MediaControllerHost, and Controller so the GC knows about their relationship
+        auto* mediaJSWrapperObject = mediaJSWrapper.toObject(&exec);
+        scope.assertNoException();
+        auto controlsHost = JSC::Identifier::fromString(&exec.vm(), "controlsHost");
 
-    ASSERT(!mediaJSWrapperObject->hasProperty(exec, controlsHost));
+        ASSERT(!mediaJSWrapperObject->hasProperty(&exec, controlsHost));
 
-    mediaJSWrapperObject->putDirect(exec->vm(), controlsHost, mediaControlsHostJSWrapper, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
+        mediaJSWrapperObject->putDirect(exec.vm(), controlsHost, mediaControlsHostJSWrapper, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
 
-    JSC::JSObject* mediaControlsHostJSWrapperObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, mediaControlsHostJSWrapper);
-    if (!mediaControlsHostJSWrapperObject)
-        return;
+        auto* mediaControlsHostJSWrapperObject = JSC::jsDynamicCast<JSC::JSObject*>(vm, mediaControlsHostJSWrapper);
+        if (!mediaControlsHostJSWrapperObject)
+            return false;
 
-    JSC::Identifier controller = JSC::Identifier::fromString(&exec->vm(), "controller");
+        auto controller = JSC::Identifier::fromString(&exec.vm(), "controller");
 
-    ASSERT(!controllerObject->hasProperty(exec, controller));
+        ASSERT(!controllerObject->hasProperty(&exec, controller));
 
-    mediaControlsHostJSWrapperObject->putDirect(exec->vm(), controller, controllerValue, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
+        mediaControlsHostJSWrapperObject->putDirect(exec.vm(), controller, controllerValue, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
 
-    updatePageScaleFactorJSProperty();
-    updateUsesLTRUserInterfaceLayoutDirectionJSProperty();
+        updatePageScaleFactorJSProperty();
+        updateUsesLTRUserInterfaceLayoutDirectionJSProperty();
 
-    if (UNLIKELY(scope.exception()))
-        scope.clearException();
+        if (UNLIKELY(scope.exception()))
+            scope.clearException();
+
+        return true;
+    });
 }
 
 void HTMLMediaElement::setMediaControlsDependOnPageScaleFactor(bool dependsOnPageScale)
@@ -7372,33 +7377,32 @@ void HTMLMediaElement::updateMediaControlsAfterPresentationModeChange()
     if (!m_mediaControlsHost || document().activeDOMObjectsAreSuspended() || document().activeDOMObjectsAreStopped())
         return;
 
-    DOMWrapperWorld& world = ensureIsolatedWorld();
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::VM& vm = globalObject->vm();
-    JSC::JSLockHolder lock(vm);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    JSC::ExecState* exec = globalObject->globalExec();
+    setupAndCallJS([this](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController&, DOMWrapperWorld&) {
+        auto& vm = globalObject.vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
 
-    JSC::JSValue controllerValue = controllerJSValue(*exec, *globalObject, *this);
-    JSC::JSObject* controllerObject = controllerValue.toObject(exec);
+        auto controllerValue = controllerJSValue(exec, globalObject, *this);
+        auto* controllerObject = controllerValue.toObject(&exec);
 
-    RETURN_IF_EXCEPTION(scope, void());
+        RETURN_IF_EXCEPTION(scope, false);
 
-    JSC::JSValue functionValue = controllerObject->get(exec, JSC::Identifier::fromString(exec, "handlePresentationModeChange"));
-    if (UNLIKELY(scope.exception()) || functionValue.isUndefinedOrNull())
-        return;
+        auto functionValue = controllerObject->get(&exec, JSC::Identifier::fromString(&exec, "handlePresentationModeChange"));
+        if (UNLIKELY(scope.exception()) || functionValue.isUndefinedOrNull())
+            return false;
 
-    JSC::JSObject* function = functionValue.toObject(exec);
-    scope.assertNoException();
-    JSC::CallData callData;
-    JSC::CallType callType = function->methodTable(vm)->getCallData(function, callData);
-    if (callType == JSC::CallType::None)
-        return;
+        auto* function = functionValue.toObject(&exec);
+        scope.assertNoException();
+        JSC::CallData callData;
+        auto callType = function->methodTable(vm)->getCallData(function, callData);
+        if (callType == JSC::CallType::None)
+            return false;
+
+        JSC::MarkedArgumentBuffer argList;
+        ASSERT(!argList.hasOverflowed());
+        JSC::call(&exec, function, callType, callData, controllerObject, argList);
 
-    JSC::MarkedArgumentBuffer argList;
-    ASSERT(!argList.hasOverflowed());
-    JSC::call(exec, function, callType, callData, controllerObject, argList);
+        return true;
+    });
 }
 
 void HTMLMediaElement::pageScaleFactorChanged()
@@ -7413,39 +7417,40 @@ void HTMLMediaElement::userInterfaceLayoutDirectionChanged()
 
 String HTMLMediaElement::getCurrentMediaControlsStatus()
 {
-    DOMWrapperWorld& world = ensureIsolatedWorld();
     ensureMediaControlsShadowRoot();
 
-    ScriptController& scriptController = document().frame()->script();
-    JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(world));
-    JSC::VM& vm = globalObject->vm();
-    JSC::JSLockHolder lock(vm);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    JSC::ExecState* exec = globalObject->globalExec();
+    String status;
+    setupAndCallJS([this, &status](JSDOMGlobalObject& globalObject, JSC::ExecState& exec, ScriptController&, DOMWrapperWorld&) {
+        auto& vm = globalObject.vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
 
-    JSC::JSValue controllerValue = controllerJSValue(*exec, *globalObject, *this);
-    JSC::JSObject* controllerObject = controllerValue.toObject(exec);
+        auto controllerValue = controllerJSValue(exec, globalObject, *this);
+        auto* controllerObject = controllerValue.toObject(&exec);
 
-    RETURN_IF_EXCEPTION(scope, emptyString());
+        RETURN_IF_EXCEPTION(scope, false);
 
-    JSC::JSValue functionValue = controllerObject->get(exec, JSC::Identifier::fromString(exec, "getCurrentControlsStatus"));
-    if (UNLIKELY(scope.exception()) || functionValue.isUndefinedOrNull())
-        return emptyString();
+        auto functionValue = controllerObject->get(&exec, JSC::Identifier::fromString(&exec, "getCurrentControlsStatus"));
+        if (UNLIKELY(scope.exception()) || functionValue.isUndefinedOrNull())
+            return false;
 
-    JSC::JSObject* function = functionValue.toObject(exec);
-    scope.assertNoException();
-    JSC::CallData callData;
-    JSC::CallType callType = function->methodTable(vm)->getCallData(function, callData);
-    JSC::MarkedArgumentBuffer argList;
-    ASSERT(!argList.hasOverflowed());
-    if (callType == JSC::CallType::None)
-        return emptyString();
+        auto* function = functionValue.toObject(&exec);
+        scope.assertNoException();
+        JSC::CallData callData;
+        auto callType = function->methodTable(vm)->getCallData(function, callData);
+        JSC::MarkedArgumentBuffer argList;
+        ASSERT(!argList.hasOverflowed());
+        if (callType == JSC::CallType::None)
+            return false;
+
+        auto outputValue = JSC::call(&exec, function, callType, callData, controllerObject, argList);
 
-    JSC::JSValue outputValue = JSC::call(exec, function, callType, callData, controllerObject, argList);
+        RETURN_IF_EXCEPTION(scope, false);
 
-    RETURN_IF_EXCEPTION(scope, emptyString());
+        status = outputValue.getString(&exec);
+        return true;
+    });
 
-    return outputValue.getString(exec);
+    return status;
 }
 #endif // ENABLE(MEDIA_CONTROLS_SCRIPT)
 
index 8a3f48b..360af86 100644 (file)
@@ -77,11 +77,13 @@ class AudioTrackList;
 class AudioTrackPrivate;
 class Blob;
 class DOMException;
+class DOMWrapperWorld;
 class DeferredPromise;
 class Event;
 class HTMLSourceElement;
 class HTMLTrackElement;
 class InbandTextTrackPrivate;
+class JSDOMGlobalObject;
 class MediaController;
 class MediaControls;
 class MediaControlsHost;
@@ -93,6 +95,7 @@ class MediaSession;
 class MediaSource;
 class MediaStream;
 class RenderMedia;
+class ScriptController;
 class ScriptExecutionContext;
 class SourceBuffer;
 class TextTrackList;
@@ -900,6 +903,9 @@ private:
     void updateCaptionContainer();
     void ensureMediaControlsShadowRoot();
 
+    using JSSetupFunction = WTF::Function<bool(JSDOMGlobalObject&, JSC::ExecState&, ScriptController&, DOMWrapperWorld&)>;
+    bool setupAndCallJS(const JSSetupFunction&);
+
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     void prepareForDocumentSuspension() final;
     void resumeFromDocumentSuspension() final;