Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: third_party/WebKit/Source/core/dom/ModuleMap.cpp

Issue 2555653002: [WIP Prototype] ES6 https://html.spec.whatwg.org/#fetch-a-single-module-script implementation (Closed)
Patch Set: address haraken/yhirano comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/dom/ModuleMap.h"
6
7 #include "bindings/core/v8/ScriptModuleResolver.h"
8 #include "core/dom/Modulator.h"
9 #include "core/dom/ModuleScript.h"
10 #include "core/loader/modulescript/ModuleScriptLoaderClient.h"
11 #include "platform/WebTaskRunner.h"
12
13 namespace blink {
14
15 // Entry struct represents a value in "module map" spec object.
16 class ModuleMap::Entry : public GarbageCollectedFinalized<Entry>,
17 public ModuleScriptLoaderClient {
18 USING_GARBAGE_COLLECTED_MIXIN(ModuleMap::Entry);
19
20 public:
21 static Entry* create(ModuleMap* map) { return new Entry(map); }
22 virtual ~Entry() {}
23
24 DECLARE_TRACE();
25
26 // Asynchronously notify the client fetched |m_moduleScript|, or register the
27 // client to receive further callbacks if |m_isFetching|.
28 void addClient(SingleModuleClient*);
29
30 // This is only to be used from ScriptModuleResolver implementations.
31 ModuleScript* retrieveModuleScriptSync() const;
32
33 private:
34 Entry(ModuleMap*);
35
36 void dispatchFinishedNotificationAsync(SingleModuleClient*);
37
38 // Implements ModuleScriptLoaderClient
39 void notifyFinishedNewSingleModule(ModuleScript*) override;
40
41 Member<ModuleScript> m_moduleScript;
42 Member<ModuleMap> m_map;
43 std::unique_ptr<WebTaskRunner> m_taskRunner;
44
45 // Correspond to the HTML spec: "fetching" state.
46 bool m_isFetching = true;
47
48 HeapHashSet<Member<SingleModuleClient>> m_clients;
49 };
50
51 ModuleMap::Entry::Entry(ModuleMap* map) : m_map(map) {
52 DCHECK(m_map);
53 m_taskRunner = m_map->modulator()->taskRunner()->clone();
54 }
55
56 DEFINE_TRACE(ModuleMap::Entry) {
57 visitor->trace(m_moduleScript);
58 visitor->trace(m_map);
59 visitor->trace(m_clients);
60 }
61
62 void ModuleMap::Entry::dispatchFinishedNotificationAsync(
63 SingleModuleClient* client) {
64 m_taskRunner->postTask(
65 BLINK_FROM_HERE,
66 WTF::bind(&SingleModuleClient::notifyFinishedSingleModule,
67 wrapPersistent(client), wrapPersistent(m_moduleScript.get())));
68 }
69
70 void ModuleMap::Entry::addClient(SingleModuleClient* newClient) {
71 DCHECK(!m_clients.contains(newClient));
72 if (!m_isFetching) {
73 DCHECK(m_clients.isEmpty());
74 dispatchFinishedNotificationAsync(newClient);
75 return;
76 }
77
78 m_clients.add(newClient);
79 }
80
81 void ModuleMap::Entry::notifyFinishedNewSingleModule(
82 ModuleScript* moduleScript) {
83 m_moduleScript = moduleScript;
84 m_isFetching = false;
85
86 if (m_moduleScript) {
87 m_map->modulator()->scriptModuleResolver()->registerModuleScript(
88 m_moduleScript);
89 }
90
91 for (const auto& client : m_clients) {
92 dispatchFinishedNotificationAsync(client);
93 }
94 m_clients.clear();
95 }
96
97 ModuleScript* ModuleMap::Entry::retrieveModuleScriptSync() const {
98 DCHECK(!m_isFetching);
99 return m_moduleScript.get();
100 }
101
102 ModuleMap::ModuleMap(Modulator* modulator) : m_modulator(modulator) {
103 DCHECK(modulator);
104 }
105
106 DEFINE_TRACE(ModuleMap) {
107 visitor->trace(m_map);
108 visitor->trace(m_modulator);
109 }
110
111 void ModuleMap::retrieveAndFetchIfNeeded(const KURL& url,
112 const KURL& baseURL,
113 SingleModuleClient* client) {
114 // https://html.spec.whatwg.org/#fetch-a-single-module-script
115
116 // Step 1. Let moduleMap be module map settings object's module map.
117 // Note: This is the ModuleMap.
118
119 // Step 2. If moduleMap[url] is "fetching", wait in parallel until that
120 // entry's value changes, then queue a task on the networking task source to
121 // proceed with running the following steps.
122 printf("ModuleMap::fetch(%s, base=%s)\n", url.getString().utf8().data(),
123 baseURL.getString().utf8().data());
124
125 MapImpl::AddResult result = m_map.set(url, nullptr);
126 Member<Entry>& entry = result.storedValue->value;
127 if (result.isNewEntry) {
128 entry = Entry::create(this);
129
130 // Steps 4-9 loads a new single module script.
131 // Delegate to ModuleScriptLoader via Modulator.
132 m_modulator->fetchNewSingleModule(url, baseURL, entry);
133 }
134
135 // Step 3. If moduleMap[url] exists, asynchronously complete this algorithm
136 // with moduleMap[url], and abort these steps.
137 // Step 10. Set moduleMap[url] to module script, and asynchronously complete
138 // this algorithm with module script.
139 entry->addClient(client);
140 }
141
142 ModuleScript* ModuleMap::retrieveFetchedModuleScript(const KURL& url) {
143 MapImpl::iterator it = m_map.find(url);
144 CHECK_NE(it, m_map.end());
145 return it->value->retrieveModuleScriptSync();
146 }
147
148 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698