2
* Copyright (C) 2019 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
27
#include "WindowEventLoop.h"
30
#include "CustomElementReactionQueue.h"
32
#include "HTMLSlotElement.h"
33
#include "Microtasks.h"
34
#include "MutationObserver.h"
35
#include "SecurityOrigin.h"
39
static HashMap<String, WindowEventLoop*>& windowEventLoopMap()
41
RELEASE_ASSERT(isMainThread());
42
static NeverDestroyed<HashMap<String, WindowEventLoop*>> map;
46
static String agentClusterKeyOrNullIfUnique(const SecurityOrigin& origin)
48
auto computeKey = [&] {
49
// https://html.spec.whatwg.org/multipage/webappapis.html#obtain-agent-cluster-key
50
if (origin.isUnique())
51
return origin.toString();
52
RegistrableDomain registrableDomain { origin.data() };
53
if (registrableDomain.isEmpty())
54
return origin.toString();
55
return makeString(origin.protocol(), "://", registrableDomain.string());
57
auto key = computeKey();
58
if (key.isEmpty() || key == "null"_s)
63
Ref<WindowEventLoop> WindowEventLoop::eventLoopForSecurityOrigin(const SecurityOrigin& origin)
65
auto key = agentClusterKeyOrNullIfUnique(origin);
69
auto addResult = windowEventLoopMap().add(key, nullptr);
70
if (UNLIKELY(addResult.isNewEntry)) {
71
auto newEventLoop = create(key);
72
addResult.iterator->value = newEventLoop.ptr();
75
return *addResult.iterator->value;
78
inline Ref<WindowEventLoop> WindowEventLoop::create(const String& agentClusterKey)
80
return adoptRef(*new WindowEventLoop(agentClusterKey));
83
inline WindowEventLoop::WindowEventLoop(const String& agentClusterKey)
84
: m_agentClusterKey(agentClusterKey)
85
, m_timer(*this, &WindowEventLoop::didReachTimeToRun)
86
, m_perpetualTaskGroupForSimilarOriginWindowAgents(*this)
90
WindowEventLoop::~WindowEventLoop()
92
if (m_agentClusterKey.isNull())
94
auto didRemove = windowEventLoopMap().remove(m_agentClusterKey);
95
RELEASE_ASSERT(didRemove);
98
void WindowEventLoop::scheduleToRun()
100
m_timer.startOneShot(0_s);
103
bool WindowEventLoop::isContextThread() const
105
return isMainThread();
108
MicrotaskQueue& WindowEventLoop::microtaskQueue()
110
if (!m_microtaskQueue)
111
m_microtaskQueue = makeUnique<MicrotaskQueue>(commonVM());
112
return *m_microtaskQueue;
115
void WindowEventLoop::didReachTimeToRun()
117
auto protectedThis = makeRef(*this); // Executing tasks may remove the last reference to this WindowEventLoop.
121
void WindowEventLoop::queueMutationObserverCompoundMicrotask()
123
if (m_mutationObserverCompoundMicrotaskQueuedFlag)
125
m_mutationObserverCompoundMicrotaskQueuedFlag = true;
126
m_perpetualTaskGroupForSimilarOriginWindowAgents.queueMicrotask([this] {
127
// We can't make a Ref to WindowEventLoop in the lambda capture as that would result in a reference cycle & leak.
128
auto protectedThis = makeRef(*this);
129
m_mutationObserverCompoundMicrotaskQueuedFlag = false;
131
// FIXME: This check doesn't exist in the spec.
132
if (m_deliveringMutationRecords)
134
m_deliveringMutationRecords = true;
135
MutationObserver::notifyMutationObservers(*this);
136
m_deliveringMutationRecords = false;
140
CustomElementQueue& WindowEventLoop::backupElementQueue()
142
if (!m_processingBackupElementQueue) {
143
m_processingBackupElementQueue = true;
144
m_perpetualTaskGroupForSimilarOriginWindowAgents.queueMicrotask([this] {
145
// We can't make a Ref to WindowEventLoop in the lambda capture as that would result in a reference cycle & leak.
146
auto protectedThis = makeRef(*this);
147
m_processingBackupElementQueue = false;
148
ASSERT(m_customElementQueue);
149
CustomElementReactionQueue::processBackupQueue(*m_customElementQueue);
152
if (!m_customElementQueue)
153
m_customElementQueue = makeUnique<CustomElementQueue>();
154
return *m_customElementQueue;
157
} // namespace WebCore