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

Side by Side Diff: third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp

Issue 2697073002: [ES6 modules] Introduce ModuleScriptLoader (Closed)
Patch Set: Created 3 years, 10 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/loader/modulescript/ModuleScriptLoader.h"
6
7 #include "core/dom/Modulator.h"
8 #include "core/dom/ModuleScript.h"
9 #include "core/loader/modulescript/ModuleScriptLoaderClient.h"
10 #include "core/loader/modulescript/ModuleScriptLoaderRegistry.h"
11 #include "platform/loader/fetch/ResourceFetcher.h"
12 #include "platform/network/mime/MIMETypeRegistry.h"
13 #include "platform/weborigin/SecurityPolicy.h"
14
15 namespace blink {
16
17 ModuleScriptLoader::ModuleScriptLoader(Modulator* modulator,
18 ModuleScriptLoaderRegistry* registry,
19 ModuleScriptLoaderClient* client)
20 : m_modulator(modulator), m_registry(registry), m_client(client) {
21 DCHECK(modulator);
22 DCHECK(registry);
23 DCHECK(client);
24 }
25
26 ModuleScriptLoader::~ModuleScriptLoader() {}
27
28 #ifndef NDEBUG
29 const char* ModuleScriptLoader::stateToString(ModuleScriptLoader::State state) {
hiroshige 2017/02/20 23:15:32 Why aren't stateToString() and m_url used in this
kouhei (in TOK) 2017/02/21 01:26:51 I used them in ::show(), which I accidentally drop
30 switch (state) {
31 case State::Initial:
32 return "Initial";
33 case State::Fetching:
34 return "Fetching";
35 case State::Finished:
36 return "Finished";
37 default:
yhirano 2017/02/17 04:59:15 No default: is needed. Please add NOTRECHED() outs
kouhei (in TOK) 2017/02/21 01:26:51 Done.
38 return "<unknown>";
39 }
40 }
41 #endif
42
43 void ModuleScriptLoader::advanceState(ModuleScriptLoader::State newState) {
44 switch (m_state) {
45 case State::Initial:
46 DCHECK_EQ(newState, State::Fetching);
47 break;
48 case State::Fetching:
49 DCHECK_EQ(newState, State::Finished);
50 break;
51 case State::Finished:
52 NOTREACHED();
53 break;
54 default:
hiroshige 2017/02/20 23:15:32 This |default| clause is also not needed.
kouhei (in TOK) 2017/02/21 01:26:51 Done.
55 NOTREACHED();
56 }
57
58 m_state = newState;
59
60 if (m_state == State::Finished) {
61 m_registry->releaseFinishedLoader(this);
62 m_client->notifyNewSingleModuleFinished(m_moduleScript);
63 }
64 }
65
66 void ModuleScriptLoader::fetch(const ModuleScriptFetchRequest& moduleRequest,
hiroshige 2017/02/20 23:15:32 Could you add a comment with the link to the spec
kouhei (in TOK) 2017/02/21 01:26:51 Done.
67 ResourceFetcher* fetcher,
68 ModuleGraphLevel level) {
69 // Step 4. Set moduleMap[url] to "fetching".
70 advanceState(State::Fetching);
71
72 // Step 5. Let request be a new request whose url is url, ...
73 ResourceRequest resourceRequest(moduleRequest.url());
74 #ifndef NDEBUG
75 m_url = moduleRequest.url();
76 #endif
77
78 // TODO(kouhei): handle "destination is destination,"
79 // ... type is "script", -> FetchResourceType is specified by
80 // ScriptResource::fetch mode is "cors", ...
hiroshige 2017/02/20 23:15:32 Perhaps we need a line break or something between
kouhei (in TOK) 2017/02/21 01:26:51 Done.
81 resourceRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS);
yhirano 2017/02/17 04:59:15 +tyoshino@: You may need to call FetchRequest::se
kouhei (in TOK) 2017/02/21 01:26:51 Done, but I'm not confident here.
tyoshino (SeeGerritForStatus) 2017/02/21 03:47:17 Yes. setCrossOriginAccessControl() is needed. Now
kouhei (in TOK) 2017/02/21 05:52:28 Done.
82 // ... credentials mode is credentials mode, ...
83 resourceRequest.setFetchCredentialsMode(moduleRequest.credentialsMode());
84 // parser metadata is parser state,
85 ResourceLoaderOptions options;
86 options.parserDisposition = moduleRequest.parserState();
87 // referrer is referrer,
88 if (!moduleRequest.referrer().isNull()) {
89 resourceRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(
90 m_modulator->referrerPolicy(), moduleRequest.url(),
91 moduleRequest.referrer()));
92 }
93 // and client is fetch client settings object. -> set by ResourceFetcher
94
95 // TODO(kouhei): what initiatorName should we set here? should we set
hiroshige 2017/02/20 23:15:32 ScriptLoader sets the initiator to |m_element->loc
kouhei (in TOK) 2017/02/21 01:26:50 I'm not sure here too. If we are to align to the s
96 // "module"?
97 // ... cryptographic nonce metadata is cryptographic nonce, ...
98 FetchRequest fetchRequest(resourceRequest, "module", options);
99 fetchRequest.setContentSecurityPolicyNonce(moduleRequest.nonce());
100
101 // Module scripts are always async.
102 fetchRequest.setDefer(FetchRequest::LazyLoad);
103
104 // Step 6. If the caller specified custom steps to perform the fetch,
105 // perform them on request, setting the is top-level flag if the top-level
106 // module fetch flag is set. Return from this algorithm, and when the custom
107 // perform the fetch steps complete with response response, run the remaining
108 // steps.
109 // Otherwise, fetch request. Return from this algorithm, and run the remaining
110 // steps as part of the fetch's process response for the response response.
111 // TODO(ServiceWorker team): Perform the "custom steps" for module usage
112 // inside service worker.
113 (void)level;
114 // Otherwise, fetch request. Return from this algorithm, and run the remaining
hiroshige 2017/02/20 23:15:32 Lines 109-110 and 114-115 are duplicated.
kouhei (in TOK) 2017/02/21 01:26:50 Done.
115 // steps as part of the fetch's process response for the response response.
116 // Note: response is always CORS-same-origin.
117 ScriptResource* resource = ScriptResource::fetch(fetchRequest, fetcher);
yhirano 2017/02/17 04:59:15 DCHECK(resource)?
kouhei (in TOK) 2017/02/21 01:26:51 Done.
hiroshige 2017/02/21 23:50:01 ScriptResource::fetch() can be return nullptr in g
kouhei (in TOK) 2017/02/22 03:52:29 You're right. We are only checking synchronous cas
yhirano 2017/02/22 08:02:57 I'm not following. It sounds we need to care about
kouhei (in TOK) 2017/02/23 03:49:26 Added test for this case/
118 setResource(resource);
hiroshige 2017/02/20 23:15:32 notifyFinished() might be called synchronously her
kouhei (in TOK) 2017/02/21 01:26:50 I think this is fine for the current ModuleScriptL
hiroshige 2017/02/21 23:50:01 Hmm, then we have to set |m_nonce| and |m_parserSt
kouhei (in TOK) 2017/02/22 03:52:29 Done.
yhirano 2017/02/22 08:02:57 In such a case, I think we should not run |setReso
kouhei (in TOK) 2017/02/23 03:49:26 Done.
119
120 m_nonce = moduleRequest.nonce();
121 m_parserState = moduleRequest.parserState();
122 m_credentialsMode = moduleRequest.credentialsMode();
123 }
124
125 bool ModuleScriptLoader::wasModuleLoadSuccessful(Resource* resource) {
126 // Implements conditions in Step 7 of
127 // https://html.spec.whatwg.org/#fetch-a-single-module-script
128
129 // - response's type is "error"
130 if (resource->errorOccurred()) {
131 return false;
132 }
133
134 const auto& response = resource->response();
135 // - response's status is not an ok status
136 if (response.isHTTP() &&
137 (response.httpStatusCode() < 200 || response.httpStatusCode() >= 300)) {
138 return false;
139 }
140
141 // The result of extracting a MIME type from response's header list
142 // (ignoring parameters) is not a JavaScript MIME type
143 // Note: For historical reasons, fetching a classic script does not include
144 // MIME type checking. In contrast, module scripts will fail to load if they
hiroshige 2017/02/20 23:15:32 Could you clarify that this refers to "response's"
kouhei (in TOK) 2017/02/21 01:26:51 This is a copy of spec text per https://html.spec.
hiroshige 2017/02/21 23:50:01 Acknowledged.
145 // are not of a correct MIME type.
146 if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(response.mimeType()))
147 return false;
148
149 return true;
150 }
151
152 // ScriptResourceClient callback handler
153 void ModuleScriptLoader::notifyFinished(Resource*) {
154 // Note: "conditions" referred in Step 7 is implemented in
155 // wasModuleLoadSuccessful().
156 // Step 7. If any of the following conditions are met, set moduleMap[url] to
157 // null, asynchronously complete this algorithm with null, and abort these
158 // steps.
159 if (!wasModuleLoadSuccessful(resource())) {
160 advanceState(State::Finished);
161 setResource(nullptr);
yhirano 2017/02/17 04:59:15 Is it preferable to move this statement into advan
kouhei (in TOK) 2017/02/21 01:26:50 Done.
162 return;
163 }
164
165 // Step 8. Let source text be the result of UTF-8 decoding response's body.
166 String sourceText = resource()->script();
167
168 // Step 9. Let module script be the result of creating a module script given
169 // source text, module map settings object, response's url, cryptographic
170 // nonce, parser state, and credentials mode.
171 m_moduleScript =
172 createModuleScript(sourceText, resource()->response().url(), m_modulator,
173 m_nonce, m_parserState, m_credentialsMode);
yhirano 2017/02/17 04:59:15 Can we use resource->resourceRequest().fetchCreden
kouhei (in TOK) 2017/02/21 01:26:50 Done.
174
175 advanceState(State::Finished);
176 setResource(nullptr);
177 }
178
179 // https://html.spec.whatwg.org/#creating-a-module-script
180 ModuleScript* ModuleScriptLoader::createModuleScript(
181 const String& sourceText,
182 const KURL& url,
183 Modulator* modulator,
184 const String& nonce,
185 ParserDisposition parserState,
186 WebURLRequest::FetchCredentialsMode credentialsMode) {
187 // Step 1. Let script be a new module script that this algorithm will
188 // subsequently initialize.
189 // Step 2. Set script's settings object to the environment settings object
190 // provided.
191 // Note: "script's settings object" will be "modulator".
192
193 // Delegate to Modulator::compileModule to process Steps 3-6.
194 ScriptModule record = modulator->compileModule(sourceText, url.getString());
hiroshige 2017/02/20 23:15:32 nit: should this local variable's name |result| in
kouhei (in TOK) 2017/02/21 01:26:50 Done.
195 if (record.isNull())
196 return nullptr;
hiroshige 2017/02/20 23:15:32 Isn't this a part of Step 6: "...return null, and
kouhei (in TOK) 2017/02/21 01:26:51 Done.
197 // Step 7. Set script's module record to result.
198 // Step 8. Set script's base URL to the script base URL provided.
199 // Step 9. Set script's cryptographic nonce to the cryptographic nonce
200 // provided.
201 // Step 10. Set script's parser state to the parser state.
202 // Step 11. Set script's credentials mode to the credentials mode provided.
203 // Step 12. Return script.
204 return ModuleScript::create(record, url, nonce, parserState, credentialsMode);
205 }
206
207 DEFINE_TRACE(ModuleScriptLoader) {
208 visitor->trace(m_modulator);
209 visitor->trace(m_moduleScript);
210 visitor->trace(m_registry);
211 visitor->trace(m_client);
212 ResourceOwner<ScriptResource>::trace(visitor);
213 }
214
215 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698