531778015f8708765aac27cbfd6e13d749a4fb7a
[WebKit.git] / Source / WebCore / bindings / js / JSDOMGlobalObjectTask.cpp
1 /*
2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSDOMGlobalObjectTask.h"
28
29 #include "ActiveDOMCallback.h"
30 #include "JSMainThreadExecState.h"
31 #include <heap/StrongInlines.h>
32 #include <runtime/Microtask.h>
33 #include <wtf/Ref.h>
34
35 using namespace JSC;
36
37 namespace WebCore {
38
39 class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback {
40 public:
41     static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
42     {
43         return adoptRef(*new JSGlobalObjectCallback(globalObject, WTFMove(task)));
44     }
45
46     void call()
47     {
48         if (!canInvokeCallback())
49             return;
50
51         Ref<JSGlobalObjectCallback> protectedThis(*this);
52         VM& vm = m_globalObject->vm();
53         JSLockHolder lock(vm);
54         auto scope = DECLARE_THROW_SCOPE(vm);
55
56         ExecState* exec = m_globalObject->globalExec();
57
58         ScriptExecutionContext* context = m_globalObject->scriptExecutionContext();
59         // We will fail to get the context if the frame has been detached.
60         if (!context)
61             return;
62
63         // When on the main thread (e.g. the document's thread), we need to make sure to
64         // push the current ExecState on to the JSMainThreadExecState stack.
65         if (context->isDocument())
66             JSMainThreadExecState::runTask(exec, m_task);
67         else
68             m_task->run(exec);
69         scope.assertNoException();
70     }
71
72 private:
73     JSGlobalObjectCallback(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
74         : ActiveDOMCallback(globalObject->scriptExecutionContext())
75         , m_globalObject(globalObject->vm(), globalObject)
76         , m_task(WTFMove(task))
77     {
78     }
79
80     Strong<JSDOMGlobalObject> m_globalObject;
81     Ref<Microtask> m_task;
82 };
83
84 JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
85     : ScriptExecutionContext::Task({ })
86 {
87     RefPtr<JSGlobalObjectCallback> callback = JSGlobalObjectCallback::create(globalObject, WTFMove(task));
88     m_task = [callback] (ScriptExecutionContext&) {
89         callback->call();
90     };
91 }
92
93 } // namespace WebCore