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

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

Issue 2695713015: WIP: Reland CompiledScript, prototype compiling in a separate task.
Patch Set: allow compile to fail, disallow restreaming (hack) Created 3 years, 9 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
1 /* 1 /*
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "core/dom/PendingScript.h" 26 #include "core/dom/PendingScript.h"
27 27
28 #include "bindings/core/v8/ScriptController.h"
28 #include "bindings/core/v8/ScriptSourceCode.h" 29 #include "bindings/core/v8/ScriptSourceCode.h"
29 #include "core/dom/Element.h" 30 #include "core/dom/Element.h"
31 #include "core/dom/ScriptLoader.h"
32 #include "core/dom/TaskRunnerHelper.h"
33 #include "core/frame/LocalFrame.h"
30 #include "core/frame/SubresourceIntegrity.h" 34 #include "core/frame/SubresourceIntegrity.h"
31 #include "platform/SharedBuffer.h" 35 #include "platform/SharedBuffer.h"
36 #include "platform/instrumentation/tracing/TraceEvent.h"
32 #include "wtf/CurrentTime.h" 37 #include "wtf/CurrentTime.h"
33 38
34 namespace blink { 39 namespace blink {
35 40
36 PendingScript* PendingScript::create(Element* element, 41 PendingScript* PendingScript::create(Element* element,
37 ScriptResource* resource) { 42 ScriptResource* resource) {
38 return new PendingScript(element, resource, TextPosition()); 43 return new PendingScript(element, resource, TextPosition());
39 } 44 }
40 45
41 PendingScript* PendingScript::create(Element* element, 46 PendingScript* PendingScript::create(Element* element,
42 const TextPosition& startingPosition) { 47 const TextPosition& startingPosition) {
43 return new PendingScript(element, nullptr, startingPosition); 48 return new PendingScript(element, nullptr, startingPosition);
44 } 49 }
45 50
46 PendingScript* PendingScript::createForTesting(ScriptResource* resource) { 51 PendingScript* PendingScript::createForTesting(ScriptResource* resource) {
47 return new PendingScript(nullptr, resource, TextPosition(), true); 52 return new PendingScript(nullptr, resource, TextPosition(), true);
48 } 53 }
49 54
50 PendingScript::PendingScript(Element* element, 55 PendingScript::PendingScript(Element* element,
51 ScriptResource* resource, 56 ScriptResource* resource,
52 const TextPosition& startingPosition, 57 const TextPosition& startingPosition,
53 bool isForTesting) 58 bool isForTesting)
54 : m_watchingForLoad(false), 59 : m_watchingForLoad(false),
60 m_readyState(resource ? kWaitingForResource : kReady),
55 m_element(element), 61 m_element(element),
56 m_startingPosition(startingPosition), 62 m_startingPosition(startingPosition),
57 m_integrityFailure(false), 63 m_integrityFailure(false),
58 m_parserBlockingLoadStartTime(0), 64 m_parserBlockingLoadStartTime(0),
59 m_client(nullptr), 65 m_client(nullptr),
60 m_isForTesting(isForTesting) { 66 m_isForTesting(isForTesting) {
61 checkState(); 67 checkState();
62 setResource(resource); 68 setResource(resource);
63 MemoryCoordinator::instance().registerClient(this); 69 MemoryCoordinator::instance().registerClient(this);
64 } 70 }
(...skipping 27 matching lines...) Expand all
92 98
93 DCHECK(!m_watchingForLoad); 99 DCHECK(!m_watchingForLoad);
94 // addClient() will call streamingFinished() if the load is complete. Callers 100 // addClient() will call streamingFinished() if the load is complete. Callers
95 // who do not expect to be re-entered from this call should not call 101 // who do not expect to be re-entered from this call should not call
96 // watchForLoad for a PendingScript which isReady. We also need to set 102 // watchForLoad for a PendingScript which isReady. We also need to set
97 // m_watchingForLoad early, since addClient() can result in calling 103 // m_watchingForLoad early, since addClient() can result in calling
98 // notifyFinished and further stopWatchingForLoad(). 104 // notifyFinished and further stopWatchingForLoad().
99 m_watchingForLoad = true; 105 m_watchingForLoad = true;
100 m_client = client; 106 m_client = client;
101 if (isReady()) 107 if (isReady())
102 m_client->pendingScriptFinished(this); 108 client->pendingScriptFinished(this);
103 } 109 }
104 110
105 void PendingScript::stopWatchingForLoad() { 111 void PendingScript::stopWatchingForLoad() {
106 if (!m_watchingForLoad) 112 if (!m_watchingForLoad)
107 return; 113 return;
108 checkState(); 114 checkState();
109 DCHECK(resource()); 115 DCHECK(resource());
110 m_client = nullptr; 116 m_client = nullptr;
111 m_watchingForLoad = false; 117 m_watchingForLoad = false;
112 } 118 }
113 119
114 Element* PendingScript::element() const { 120 Element* PendingScript::element() const {
115 // As mentioned in the comment at |m_element| declaration, |m_element| 121 // As mentioned in the comment at |m_element| declaration, |m_element|
116 // must points to the corresponding ScriptLoader's element. 122 // must points to the corresponding ScriptLoader's element.
117 CHECK(m_element); 123 CHECK(m_element);
118 return m_element.get(); 124 return m_element.get();
119 } 125 }
120 126
121 void PendingScript::streamingFinished() { 127 void PendingScript::streamingFinished() {
122 checkState(); 128 checkState();
123 DCHECK(resource()); 129 DCHECK(resource());
130 fetchFinished();
131 }
132
133 void PendingScript::fetchFinished() {
134 advanceReadyState(kWaitingForCompile);
135
136 TRACE_EVENT_WITH_FLOW0("blink", "PendingScript compile", this,
137 TRACE_EVENT_FLAG_FLOW_OUT);
138 LocalFrame* frame = m_element ? m_element->document().frame() : nullptr;
139 if (!frame) {
140 // TODO(jbroman): A way of telling the client that it failed, without making
141 // the client try again, would be great.
142 compileFinished();
143 return;
144 }
145
146 ScriptState::Scope scope(ScriptState::forMainWorld(frame));
147 bool errorOccurred;
148 ScriptSourceCode sourceCode = getSource(KURL(), errorOccurred);
149
150 if (errorOccurred) {
151 // TODO(jbroman): A way of telling the client that it failed, without making
152 // the client try again, would be great.
153 compileFinished();
154 return;
155 }
156
157 const bool isExternalScript = true;
158 AccessControlStatus accessControlStatus =
159 ScriptLoader::accessControlStatusForScript(
160 isExternalScript, resource(),
161 m_element->document().getSecurityOrigin());
162 m_compiledScript =
163 frame->script().compileScriptInMainWorld(sourceCode, accessControlStatus);
164 // TODO(jbroman): Can this fail? Yes, it can.
165 // CHECK(m_compiledScript) << "no compiled script? :'(";
166 TaskRunnerHelper::get(TaskType::Networking, frame)
167 ->postTask(FROM_HERE, WTF::bind(&PendingScript::compileFinished,
168 wrapPersistent(this)));
169 }
170
171 void PendingScript::compileFinished() {
172 TRACE_EVENT_WITH_FLOW0("blink", "PendingScript compile", this,
173 TRACE_EVENT_FLAG_FLOW_IN);
174 advanceReadyState(kReady);
124 if (m_client) 175 if (m_client)
125 m_client->pendingScriptFinished(this); 176 m_client->pendingScriptFinished(this);
126 } 177 }
127 178
128 void PendingScript::markParserBlockingLoadStartTime() { 179 void PendingScript::markParserBlockingLoadStartTime() {
129 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0); 180 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0);
130 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime(); 181 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime();
131 } 182 }
132 183
133 // Returns true if SRI check passed. 184 // Returns true if SRI check passed.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 // the Fetch algorithm, this should be fixed by having separate Response 246 // the Fetch algorithm, this should be fixed by having separate Response
196 // objects (perhaps attached to identical Resource objects) per request. 247 // objects (perhaps attached to identical Resource objects) per request.
197 // 248 //
198 // See https://crbug.com/500701 for more information. 249 // See https://crbug.com/500701 for more information.
199 checkState(); 250 checkState();
200 if (m_element) 251 if (m_element)
201 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element); 252 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element);
202 253
203 // If script streaming is in use, the client will be notified in 254 // If script streaming is in use, the client will be notified in
204 // streamingFinished. 255 // streamingFinished.
205 if (m_streamer) 256 if (m_streamer) {
257 advanceReadyState(kWaitingForStreaming);
206 m_streamer->notifyFinished(resource); 258 m_streamer->notifyFinished(resource);
207 else if (m_client) 259 } else {
208 m_client->pendingScriptFinished(this); 260 fetchFinished();
261 }
209 } 262 }
210 263
211 void PendingScript::notifyAppendData(ScriptResource* resource) { 264 void PendingScript::notifyAppendData(ScriptResource* resource) {
212 if (m_streamer) 265 if (m_streamer)
213 m_streamer->notifyAppendData(resource); 266 m_streamer->notifyAppendData(resource);
214 } 267 }
215 268
216 DEFINE_TRACE(PendingScript) { 269 DEFINE_TRACE(PendingScript) {
217 visitor->trace(m_element); 270 visitor->trace(m_element);
218 visitor->trace(m_streamer); 271 visitor->trace(m_streamer);
219 visitor->trace(m_client); 272 visitor->trace(m_client);
273 visitor->trace(m_compiledScript);
220 ResourceOwner<ScriptResource>::trace(visitor); 274 ResourceOwner<ScriptResource>::trace(visitor);
221 MemoryCoordinatorClient::trace(visitor); 275 MemoryCoordinatorClient::trace(visitor);
222 } 276 }
223 277
224 ScriptSourceCode PendingScript::getSource(const KURL& documentURL, 278 ScriptSourceCode PendingScript::getSource(const KURL& documentURL,
225 bool& errorOccurred) const { 279 bool& errorOccurred) const {
226 checkState(); 280 checkState();
227 281
228 errorOccurred = this->errorOccurred(); 282 errorOccurred = this->errorOccurred();
229 if (resource()) { 283 if (resource()) {
230 DCHECK(resource()->isLoaded()); 284 DCHECK(resource()->isLoaded());
231 if (m_streamer && !m_streamer->streamingSuppressed()) 285 // Avoid consuming the streamed source code more than once.
286 // TODO(jbroman): Update this if we don't always do the precompile step.
287 if (m_streamer && !m_streamer->streamingSuppressed() &&
288 m_readyState < ReadyState::kReady) {
232 return ScriptSourceCode(m_streamer, resource()); 289 return ScriptSourceCode(m_streamer, resource());
290 }
233 return ScriptSourceCode(resource()); 291 return ScriptSourceCode(resource());
234 } 292 }
235 293
236 return ScriptSourceCode(m_element->textContent(), documentURL, 294 return ScriptSourceCode(m_element->textContent(), documentURL,
237 startingPosition()); 295 startingPosition());
238 } 296 }
239 297
240 void PendingScript::setStreamer(ScriptStreamer* streamer) { 298 void PendingScript::setStreamer(ScriptStreamer* streamer) {
241 DCHECK(!m_streamer); 299 DCHECK(!m_streamer);
242 DCHECK(!m_watchingForLoad); 300 DCHECK(!m_watchingForLoad);
301 DCHECK(!streamer->isFinished());
302 DCHECK_LT(m_readyState, kWaitingForStreaming);
243 m_streamer = streamer; 303 m_streamer = streamer;
244 checkState(); 304 checkState();
245 } 305 }
246 306
247 bool PendingScript::isReady() const { 307 bool PendingScript::isReady() const {
248 checkState(); 308 checkState();
249 if (resource()) { 309 return m_readyState == kReady;
250 return resource()->isLoaded() && (!m_streamer || m_streamer->isFinished());
251 }
252
253 return true;
254 } 310 }
255 311
256 bool PendingScript::errorOccurred() const { 312 bool PendingScript::errorOccurred() const {
257 checkState(); 313 checkState();
258 if (resource()) 314 if (resource())
259 return resource()->errorOccurred() || m_integrityFailure; 315 return resource()->errorOccurred() || m_integrityFailure;
260 316
261 return false; 317 return false;
262 } 318 }
263 319
264 void PendingScript::onPurgeMemory() { 320 void PendingScript::onPurgeMemory() {
265 checkState(); 321 checkState();
266 if (!m_streamer) 322 if (!m_streamer)
267 return; 323 return;
268 m_streamer->cancel(); 324 m_streamer->cancel();
269 m_streamer = nullptr; 325 m_streamer = nullptr;
270 } 326 }
271 327
272 } // namespace blink 328 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/PendingScript.h ('k') | third_party/WebKit/Source/core/dom/ScriptLoader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698