OLD | NEW |
---|---|
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 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
49 #include <inttypes.h> | 49 #include <inttypes.h> |
50 #include <memory> | 50 #include <memory> |
51 | 51 |
52 namespace blink { | 52 namespace blink { |
53 | 53 |
54 namespace { | 54 namespace { |
55 | 55 |
56 // TODO(bmcquade): move this to a shared location if we find ourselves wanting | 56 // TODO(bmcquade): move this to a shared location if we find ourselves wanting |
57 // to trace similar data elsewhere in the codebase. | 57 // to trace similar data elsewhere in the codebase. |
58 std::unique_ptr<TracedValue> getTraceArgsForScriptElement( | 58 std::unique_ptr<TracedValue> getTraceArgsForScriptLoaderClient( |
59 Element* element, | 59 ScriptLoaderClient* client, |
60 const TextPosition& textPosition) { | 60 const TextPosition& textPosition) { |
61 std::unique_ptr<TracedValue> value = TracedValue::create(); | 61 std::unique_ptr<TracedValue> value = TracedValue::create(); |
62 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element); | 62 ScriptLoader* scriptLoader = client->loader(); |
63 if (scriptLoader && scriptLoader->resource()) | 63 if (scriptLoader && scriptLoader->resource()) |
64 value->setString("url", scriptLoader->resource()->url().getString()); | 64 value->setString("url", scriptLoader->resource()->url().getString()); |
65 if (element->ownerDocument() && element->ownerDocument()->frame()) { | 65 if (client->document().frame()) { |
hiroshige
2017/03/01 00:58:15
This changes the behavior: ownerDocument() -> docu
Nate Chapin
2017/03/01 21:34:59
Node::document() and Node::ownerDocument() are equ
hiroshige
2017/03/06 22:54:03
Acknowledged.
| |
66 value->setString( | 66 value->setString( |
67 "frame", | 67 "frame", |
68 String::format("0x%" PRIx64, | 68 String::format("0x%" PRIx64, |
69 static_cast<uint64_t>(reinterpret_cast<intptr_t>( | 69 static_cast<uint64_t>(reinterpret_cast<intptr_t>( |
70 element->ownerDocument()->frame())))); | 70 client->document().frame())))); |
71 } | 71 } |
72 if (textPosition.m_line.zeroBasedInt() > 0 || | 72 if (textPosition.m_line.zeroBasedInt() > 0 || |
73 textPosition.m_column.zeroBasedInt() > 0) { | 73 textPosition.m_column.zeroBasedInt() > 0) { |
74 value->setInteger("lineNumber", textPosition.m_line.oneBasedInt()); | 74 value->setInteger("lineNumber", textPosition.m_line.oneBasedInt()); |
75 value->setInteger("columnNumber", textPosition.m_column.oneBasedInt()); | 75 value->setInteger("columnNumber", textPosition.m_column.oneBasedInt()); |
76 } | 76 } |
77 return value; | 77 return value; |
78 } | 78 } |
79 | 79 |
80 bool doExecuteScript(Element* scriptElement, | 80 bool doExecuteScript(ScriptLoaderClient* client, |
81 const ScriptSourceCode& sourceCode, | 81 const ScriptSourceCode& sourceCode, |
82 const TextPosition& textPosition) { | 82 const TextPosition& textPosition) { |
83 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(scriptElement); | 83 ScriptLoader* scriptLoader = client->loader(); |
84 DCHECK(scriptLoader); | 84 DCHECK(scriptLoader); |
85 TRACE_EVENT_WITH_FLOW1( | 85 TRACE_EVENT_WITH_FLOW1( |
86 "blink", "HTMLParserScriptRunner ExecuteScript", scriptElement, | 86 "blink", "HTMLParserScriptRunner ExecuteScript", client, |
Nate Chapin
2017/02/28 21:39:29
Here and below: these TRACE_EVENT changes are prob
| |
87 TRACE_EVENT_FLAG_FLOW_IN, "data", | 87 TRACE_EVENT_FLAG_FLOW_IN, "data", |
88 getTraceArgsForScriptElement(scriptElement, textPosition)); | 88 getTraceArgsForScriptLoaderClient(client, textPosition)); |
89 return scriptLoader->executeScript(sourceCode); | 89 return scriptLoader->executeScript(sourceCode); |
90 } | 90 } |
91 | 91 |
92 void traceParserBlockingScript(const PendingScript* pendingScript, | 92 void traceParserBlockingScript(const PendingScript* pendingScript, |
93 bool waitingForResources) { | 93 bool waitingForResources) { |
94 // The HTML parser must yield before executing script in the following | 94 // The HTML parser must yield before executing script in the following |
95 // cases: | 95 // cases: |
96 // * the script's execution is blocked on the completed load of the script | 96 // * the script's execution is blocked on the completed load of the script |
97 // resource | 97 // resource |
98 // (https://html.spec.whatwg.org/multipage/scripting.html#pending-parsing-bl ocking-script) | 98 // (https://html.spec.whatwg.org/multipage/scripting.html#pending-parsing-bl ocking-script) |
99 // * the script's execution is blocked on the load of a style sheet or other | 99 // * the script's execution is blocked on the load of a style sheet or other |
100 // resources that are blocking scripts | 100 // resources that are blocking scripts |
101 // (https://html.spec.whatwg.org/multipage/semantics.html#a-style-sheet-that -is-blocking-scripts) | 101 // (https://html.spec.whatwg.org/multipage/semantics.html#a-style-sheet-that -is-blocking-scripts) |
102 // | 102 // |
103 // Both of these cases can introduce significant latency when loading a | 103 // Both of these cases can introduce significant latency when loading a |
104 // web page, especially for users on slow connections, since the HTML parser | 104 // web page, especially for users on slow connections, since the HTML parser |
105 // must yield until the blocking resources finish loading. | 105 // must yield until the blocking resources finish loading. |
106 // | 106 // |
107 // We trace these parser yields here using flow events, so we can track | 107 // We trace these parser yields here using flow events, so we can track |
108 // both when these yields occur, as well as how long the parser had | 108 // both when these yields occur, as well as how long the parser had |
109 // to yield. The connecting flow events are traced once the parser becomes | 109 // to yield. The connecting flow events are traced once the parser becomes |
110 // unblocked when the script actually executes, in doExecuteScript. | 110 // unblocked when the script actually executes, in doExecuteScript. |
111 Element* element = pendingScript->element(); | 111 ScriptLoaderClient* client = pendingScript->scriptLoaderClient(); |
112 if (!element) | 112 if (!client) |
113 return; | 113 return; |
114 TextPosition scriptStartPosition = pendingScript->startingPosition(); | 114 TextPosition scriptStartPosition = pendingScript->startingPosition(); |
115 if (!pendingScript->isReady()) { | 115 if (!pendingScript->isReady()) { |
116 if (waitingForResources) { | 116 if (waitingForResources) { |
117 TRACE_EVENT_WITH_FLOW1( | 117 TRACE_EVENT_WITH_FLOW1( |
118 "blink", "YieldParserForScriptLoadAndBlockingResources", element, | 118 "blink", "YieldParserForScriptLoadAndBlockingResources", client, |
119 TRACE_EVENT_FLAG_FLOW_OUT, "data", | 119 TRACE_EVENT_FLAG_FLOW_OUT, "data", |
120 getTraceArgsForScriptElement(element, scriptStartPosition)); | 120 getTraceArgsForScriptLoaderClient(client, scriptStartPosition)); |
121 } else { | 121 } else { |
122 TRACE_EVENT_WITH_FLOW1( | 122 TRACE_EVENT_WITH_FLOW1( |
123 "blink", "YieldParserForScriptLoad", element, | 123 "blink", "YieldParserForScriptLoad", client, |
124 TRACE_EVENT_FLAG_FLOW_OUT, "data", | 124 TRACE_EVENT_FLAG_FLOW_OUT, "data", |
125 getTraceArgsForScriptElement(element, scriptStartPosition)); | 125 getTraceArgsForScriptLoaderClient(client, scriptStartPosition)); |
126 } | 126 } |
127 } else if (waitingForResources) { | 127 } else if (waitingForResources) { |
128 TRACE_EVENT_WITH_FLOW1( | 128 TRACE_EVENT_WITH_FLOW1( |
129 "blink", "YieldParserForScriptBlockingResources", element, | 129 "blink", "YieldParserForScriptBlockingResources", client, |
130 TRACE_EVENT_FLAG_FLOW_OUT, "data", | 130 TRACE_EVENT_FLAG_FLOW_OUT, "data", |
131 getTraceArgsForScriptElement(element, scriptStartPosition)); | 131 getTraceArgsForScriptLoaderClient(client, scriptStartPosition)); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 static KURL documentURLForScriptExecution(Document* document) { | 135 static KURL documentURLForScriptExecution(Document* document) { |
136 if (!document) | 136 if (!document) |
137 return KURL(); | 137 return KURL(); |
138 | 138 |
139 if (!document->frame()) { | 139 if (!document->frame()) { |
140 if (document->importsController()) | 140 if (document->importsController()) |
141 return document->url(); | 141 return document->url(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 // The parser cannot be unblocked as a microtask requested another | 218 // The parser cannot be unblocked as a microtask requested another |
219 // resource | 219 // resource |
220 if (!m_document->isScriptExecutionReady()) | 220 if (!m_document->isScriptExecutionReady()) |
221 return; | 221 return; |
222 } | 222 } |
223 } | 223 } |
224 | 224 |
225 TextPosition scriptStartPosition = pendingScript->startingPosition(); | 225 TextPosition scriptStartPosition = pendingScript->startingPosition(); |
226 double scriptParserBlockingTime = | 226 double scriptParserBlockingTime = |
227 pendingScript->parserBlockingLoadStartTime(); | 227 pendingScript->parserBlockingLoadStartTime(); |
228 Element* element = pendingScript->element(); | 228 ScriptLoaderClient* client = pendingScript->scriptLoaderClient(); |
229 | 229 |
230 // 1. "Let the script be the pending parsing-blocking script. | 230 // 1. "Let the script be the pending parsing-blocking script. |
231 // There is no longer a pending parsing-blocking script." | 231 // There is no longer a pending parsing-blocking script." |
232 // Clear the pending script before possible re-entrancy from executeScript() | 232 // Clear the pending script before possible re-entrancy from executeScript() |
233 pendingScript->dispose(); | 233 pendingScript->dispose(); |
234 pendingScript = nullptr; | 234 pendingScript = nullptr; |
235 | 235 |
236 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { | 236 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { |
237 m_parserBlockingScript = nullptr; | 237 m_parserBlockingScript = nullptr; |
238 } | 238 } |
239 | 239 |
240 if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element)) { | 240 if (ScriptLoader* scriptLoader = client->loader()) { |
241 // 7. "Increment the parser's script nesting level by one (it should be | 241 // 7. "Increment the parser's script nesting level by one (it should be |
242 // zero before this step, so this sets it to one)." | 242 // zero before this step, so this sets it to one)." |
243 HTMLParserReentryPermit::ScriptNestingLevelIncrementer | 243 HTMLParserReentryPermit::ScriptNestingLevelIncrementer |
244 nestingLevelIncrementer = | 244 nestingLevelIncrementer = |
245 m_reentryPermit->incrementScriptNestingLevel(); | 245 m_reentryPermit->incrementScriptNestingLevel(); |
246 | 246 |
247 IgnoreDestructiveWriteCountIncrementer | 247 IgnoreDestructiveWriteCountIncrementer |
248 ignoreDestructiveWriteCountIncrementer(m_document); | 248 ignoreDestructiveWriteCountIncrementer(m_document); |
249 | 249 |
250 // 8. "Execute the script." | 250 // 8. "Execute the script." |
251 if (errorOccurred) { | 251 if (errorOccurred) { |
252 TRACE_EVENT_WITH_FLOW1( | 252 TRACE_EVENT_WITH_FLOW1( |
253 "blink", "HTMLParserScriptRunner ExecuteScriptFailed", element, | 253 "blink", "HTMLParserScriptRunner ExecuteScriptFailed", client, |
254 TRACE_EVENT_FLAG_FLOW_IN, "data", | 254 TRACE_EVENT_FLAG_FLOW_IN, "data", |
255 getTraceArgsForScriptElement(element, scriptStartPosition)); | 255 getTraceArgsForScriptLoaderClient(client, scriptStartPosition)); |
256 scriptLoader->dispatchErrorEvent(); | 256 scriptLoader->dispatchErrorEvent(); |
257 } else { | 257 } else { |
258 DCHECK(isExecutingScript()); | 258 DCHECK(isExecutingScript()); |
259 if (scriptParserBlockingTime > 0.0) { | 259 if (scriptParserBlockingTime > 0.0) { |
260 DocumentParserTiming::from(*m_document) | 260 DocumentParserTiming::from(*m_document) |
261 .recordParserBlockedOnScriptLoadDuration( | 261 .recordParserBlockedOnScriptLoadDuration( |
262 monotonicallyIncreasingTime() - scriptParserBlockingTime, | 262 monotonicallyIncreasingTime() - scriptParserBlockingTime, |
263 scriptLoader->wasCreatedDuringDocumentWrite()); | 263 scriptLoader->wasCreatedDuringDocumentWrite()); |
264 } | 264 } |
265 if (!doExecuteScript(element, sourceCode, scriptStartPosition)) { | 265 if (!doExecuteScript(client, sourceCode, scriptStartPosition)) { |
266 scriptLoader->dispatchErrorEvent(); | 266 scriptLoader->dispatchErrorEvent(); |
267 } else { | 267 } else { |
268 element->dispatchEvent(Event::create(EventTypeNames::load)); | 268 client->dispatchLoadEvent(); |
hiroshige
2017/03/01 00:58:15
Hmm. Conceptually I think we should call scriptLoa
Nate Chapin
2017/03/01 21:34:59
Yeah, I considered calling scriptLoader->dispatchL
| |
269 } | 269 } |
270 } | 270 } |
271 | 271 |
272 // 9. "Decrement the parser's script nesting level by one. | 272 // 9. "Decrement the parser's script nesting level by one. |
273 // If the parser's script nesting level is zero | 273 // If the parser's script nesting level is zero |
274 // (which it always should be at this point), | 274 // (which it always should be at this point), |
275 // then set the parser pause flag to false." | 275 // then set the parser pause flag to false." |
276 // This is implemented by ~ScriptNestingLevelIncrementer(). | 276 // This is implemented by ~ScriptNestingLevelIncrementer(). |
277 } | 277 } |
278 | 278 |
279 DCHECK(!isExecutingScript()); | 279 DCHECK(!isExecutingScript()); |
280 } | 280 } |
281 | 281 |
282 void fetchBlockedDocWriteScript(Element* script, | 282 void fetchBlockedDocWriteScript(ScriptLoaderClient* client, |
283 bool isParserInserted, | 283 bool isParserInserted, |
284 const TextPosition& scriptStartPosition) { | 284 const TextPosition& scriptStartPosition) { |
285 DCHECK(script); | 285 DCHECK(client); |
286 | 286 |
287 ScriptLoader* scriptLoader = | 287 ScriptLoader* scriptLoader = |
288 ScriptLoader::create(script, isParserInserted, false, false); | 288 ScriptLoader::create(client, isParserInserted, false, false); |
289 DCHECK(scriptLoader); | 289 DCHECK(scriptLoader); |
290 scriptLoader->setFetchDocWrittenScriptDeferIdle(); | 290 scriptLoader->setFetchDocWrittenScriptDeferIdle(); |
291 scriptLoader->prepareScript(scriptStartPosition); | 291 scriptLoader->prepareScript(scriptStartPosition); |
292 } | 292 } |
293 | 293 |
294 void emitWarningForDocWriteScripts(const String& url, Document& document) { | 294 void emitWarningForDocWriteScripts(const String& url, Document& document) { |
295 String message = | 295 String message = |
296 "The Parser-blocking, cross site (i.e. different eTLD+1) " | 296 "The Parser-blocking, cross site (i.e. different eTLD+1) " |
297 "script, " + | 297 "script, " + |
298 url + | 298 url + |
(...skipping 21 matching lines...) Expand all Loading... | |
320 PendingScript* pendingScript) { | 320 PendingScript* pendingScript) { |
321 // If the script was blocked as part of document.write intervention, | 321 // If the script was blocked as part of document.write intervention, |
322 // then send an asynchronous GET request with an interventions header. | 322 // then send an asynchronous GET request with an interventions header. |
323 | 323 |
324 if (!parserBlockingScript()) | 324 if (!parserBlockingScript()) |
325 return; | 325 return; |
326 | 326 |
327 if (parserBlockingScript() != pendingScript) | 327 if (parserBlockingScript() != pendingScript) |
328 return; | 328 return; |
329 | 329 |
330 Element* element = parserBlockingScript()->element(); | 330 ScriptLoaderClient* client = parserBlockingScript()->scriptLoaderClient(); |
331 | 331 |
332 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element); | 332 ScriptLoader* scriptLoader = client->loader(); |
333 if (!scriptLoader || !scriptLoader->disallowedFetchForDocWrittenScript()) | 333 if (!scriptLoader || !scriptLoader->disallowedFetchForDocWrittenScript()) |
334 return; | 334 return; |
335 | 335 |
336 if (!pendingScript->errorOccurred()) { | 336 if (!pendingScript->errorOccurred()) { |
337 emitWarningForDocWriteScripts(pendingScript->resource()->url().getString(), | 337 emitWarningForDocWriteScripts(pendingScript->resource()->url().getString(), |
338 *m_document); | 338 *m_document); |
339 return; | 339 return; |
340 } | 340 } |
341 | 341 |
342 // Due to dependency violation, not able to check the exact error to be | 342 // Due to dependency violation, not able to check the exact error to be |
343 // ERR_CACHE_MISS but other errors are rare with | 343 // ERR_CACHE_MISS but other errors are rare with |
344 // WebCachePolicy::ReturnCacheDataDontLoad. | 344 // WebCachePolicy::ReturnCacheDataDontLoad. |
345 | 345 |
346 emitErrorForDocWriteScripts(pendingScript->resource()->url().getString(), | 346 emitErrorForDocWriteScripts(pendingScript->resource()->url().getString(), |
347 *m_document); | 347 *m_document); |
348 TextPosition startingPosition = parserBlockingScript()->startingPosition(); | 348 TextPosition startingPosition = parserBlockingScript()->startingPosition(); |
349 bool isParserInserted = scriptLoader->isParserInserted(); | 349 bool isParserInserted = scriptLoader->isParserInserted(); |
350 // Remove this resource entry from memory cache as the new request | 350 // Remove this resource entry from memory cache as the new request |
351 // should not join onto this existing entry. | 351 // should not join onto this existing entry. |
352 memoryCache()->remove(pendingScript->resource()); | 352 memoryCache()->remove(pendingScript->resource()); |
353 fetchBlockedDocWriteScript(element, isParserInserted, startingPosition); | 353 fetchBlockedDocWriteScript(client, isParserInserted, startingPosition); |
354 } | 354 } |
355 | 355 |
356 void HTMLParserScriptRunner::pendingScriptFinished( | 356 void HTMLParserScriptRunner::pendingScriptFinished( |
357 PendingScript* pendingScript) { | 357 PendingScript* pendingScript) { |
358 // Handle cancellations of parser-blocking script loads without | 358 // Handle cancellations of parser-blocking script loads without |
359 // notifying the host (i.e., parser) if these were initiated by nested | 359 // notifying the host (i.e., parser) if these were initiated by nested |
360 // document.write()s. The cancellation may have been triggered by | 360 // document.write()s. The cancellation may have been triggered by |
361 // script execution to signal an abrupt stop (e.g., window.close().) | 361 // script execution to signal an abrupt stop (e.g., window.close().) |
362 // | 362 // |
363 // The parser is unprepared to be told, and doesn't need to be. | 363 // The parser is unprepared to be told, and doesn't need to be. |
(...skipping 10 matching lines...) Expand all Loading... | |
374 } | 374 } |
375 | 375 |
376 // 'An end tag whose tag name is "script"' | 376 // 'An end tag whose tag name is "script"' |
377 // https://html.spec.whatwg.org/#scriptEndTag | 377 // https://html.spec.whatwg.org/#scriptEndTag |
378 // | 378 // |
379 // Script handling lives outside the tree builder to keep each class simple. | 379 // Script handling lives outside the tree builder to keep each class simple. |
380 void HTMLParserScriptRunner::processScriptElement( | 380 void HTMLParserScriptRunner::processScriptElement( |
381 Element* scriptElement, | 381 Element* scriptElement, |
382 const TextPosition& scriptStartPosition) { | 382 const TextPosition& scriptStartPosition) { |
383 DCHECK(scriptElement); | 383 DCHECK(scriptElement); |
384 TRACE_EVENT1( | 384 |
385 "blink", "HTMLParserScriptRunner::execute", "data", | |
386 getTraceArgsForScriptElement(scriptElement, scriptStartPosition)); | |
387 // FIXME: If scripting is disabled, always just return. | 385 // FIXME: If scripting is disabled, always just return. |
388 | 386 |
389 bool hadPreloadScanner = m_host->hasPreloadScanner(); | 387 bool hadPreloadScanner = m_host->hasPreloadScanner(); |
390 | 388 |
391 // Initial steps of 'An end tag whose tag name is "script"'. | 389 // Initial steps of 'An end tag whose tag name is "script"'. |
392 // Try to execute the script given to us. | 390 // Try to execute the script given to us. |
393 processScriptElementInternal(scriptElement, scriptStartPosition); | 391 processScriptElementInternal(scriptElement, scriptStartPosition); |
394 | 392 |
395 // "At this stage, if there is a pending parsing-blocking script, then:" | 393 // "At this stage, if there is a pending parsing-blocking script, then:" |
396 if (hasParserBlockingScript()) { | 394 if (hasParserBlockingScript()) { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
573 DCHECK(pendingScript->resource()); | 571 DCHECK(pendingScript->resource()); |
574 | 572 |
575 // "Add the element to the end of the list of scripts that will execute | 573 // "Add the element to the end of the list of scripts that will execute |
576 // when the document has finished parsing associated with the Document | 574 // when the document has finished parsing associated with the Document |
577 // of the parser that created the element." | 575 // of the parser that created the element." |
578 m_scriptsToExecuteAfterParsing.append(pendingScript); | 576 m_scriptsToExecuteAfterParsing.append(pendingScript); |
579 } | 577 } |
580 | 578 |
581 PendingScript* HTMLParserScriptRunner::requestPendingScript( | 579 PendingScript* HTMLParserScriptRunner::requestPendingScript( |
582 Element* element) const { | 580 Element* element) const { |
583 ScriptResource* resource = toScriptLoaderIfPossible(element)->resource(); | 581 ScriptLoaderClient* client = |
582 ScriptLoaderClient::fromElementIfPossible(element); | |
hiroshige
2017/03/01 00:58:15
Probably we can remove fromElementIfPossible() cal
Nate Chapin
2017/03/01 21:35:00
Possibly, but that requires changing PendingScript
hiroshige
2017/03/06 22:54:03
Acknowledged.
| |
583 ScriptResource* resource = client->loader()->resource(); | |
584 // Here |resource| should be non-null. If it were nullptr, | 584 // Here |resource| should be non-null. If it were nullptr, |
585 // ScriptLoader::fetchScript() should have returned false and | 585 // ScriptLoader::fetchScript() should have returned false and |
586 // thus the control shouldn't have reached here. | 586 // thus the control shouldn't have reached here. |
587 CHECK(resource); | 587 CHECK(resource); |
588 return PendingScript::create(element, resource); | 588 return PendingScript::create(client, resource); |
589 } | 589 } |
590 | 590 |
591 // The initial steps for 'An end tag whose tag name is "script"' | 591 // The initial steps for 'An end tag whose tag name is "script"' |
592 // https://html.spec.whatwg.org/#scriptEndTag | 592 // https://html.spec.whatwg.org/#scriptEndTag |
593 void HTMLParserScriptRunner::processScriptElementInternal( | 593 void HTMLParserScriptRunner::processScriptElementInternal( |
594 Element* script, | 594 Element* script, |
595 const TextPosition& scriptStartPosition) { | 595 const TextPosition& scriptStartPosition) { |
596 DCHECK(m_document); | 596 DCHECK(m_document); |
597 DCHECK(!hasParserBlockingScript()); | 597 DCHECK(!hasParserBlockingScript()); |
598 { | 598 { |
599 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(script); | 599 ScriptLoaderClient* client = |
600 ScriptLoaderClient::fromElementIfPossible(script); | |
601 if (!client) | |
hiroshige
2017/03/01 00:58:15
Shouldn't |client| always non-null because we expe
Nate Chapin
2017/03/01 21:34:59
It should be, I was just copying the pattern of th
| |
602 return; | |
603 ScriptLoader* scriptLoader = client->loader(); | |
600 | 604 |
601 // This contains both a DCHECK and a null check since we should not | 605 // This contains both a DCHECK and a null check since we should not |
602 // be getting into the case of a null script element, but seem to be from | 606 // be getting into the case of a null script element, but seem to be from |
603 // time to time. The assertion is left in to help find those cases and | 607 // time to time. The assertion is left in to help find those cases and |
604 // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. | 608 // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. |
605 DCHECK(scriptLoader); | 609 DCHECK(scriptLoader); |
606 if (!scriptLoader) | 610 if (!scriptLoader) |
607 return; | 611 return; |
608 | 612 |
613 TRACE_EVENT1( | |
614 "blink", "HTMLParserScriptRunner::execute", "data", | |
615 getTraceArgsForScriptLoaderClient(client, scriptStartPosition)); | |
609 DCHECK(scriptLoader->isParserInserted()); | 616 DCHECK(scriptLoader->isParserInserted()); |
610 | 617 |
611 if (!isExecutingScript()) | 618 if (!isExecutingScript()) |
612 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); | 619 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); |
613 | 620 |
614 // "Let the old insertion point have the same value as the current | 621 // "Let the old insertion point have the same value as the current |
615 // insertion point. | 622 // insertion point. |
616 // Let the insertion point be just before the next input character." | 623 // Let the insertion point be just before the next input character." |
617 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 624 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
618 | 625 |
(...skipping 18 matching lines...) Expand all Loading... | |
637 } else if (scriptLoader->readyToBeParserExecuted()) { | 644 } else if (scriptLoader->readyToBeParserExecuted()) { |
638 // 5th Clause of Step 23. | 645 // 5th Clause of Step 23. |
639 // "If ... it's an HTML parser | 646 // "If ... it's an HTML parser |
640 // whose script nesting level is not greater than one" | 647 // whose script nesting level is not greater than one" |
641 if (m_reentryPermit->scriptNestingLevel() == 1u) { | 648 if (m_reentryPermit->scriptNestingLevel() == 1u) { |
642 // "The element is the pending parsing-blocking script of the | 649 // "The element is the pending parsing-blocking script of the |
643 // Document of the parser that created the element. | 650 // Document of the parser that created the element. |
644 // (There can only be one such script per Document at a time.)" | 651 // (There can only be one such script per Document at a time.)" |
645 CHECK(!m_parserBlockingScript); | 652 CHECK(!m_parserBlockingScript); |
646 m_parserBlockingScript = | 653 m_parserBlockingScript = |
647 PendingScript::create(script, scriptStartPosition); | 654 PendingScript::create(client, scriptStartPosition); |
648 } else { | 655 } else { |
649 // 6th Clause of Step 23. | 656 // 6th Clause of Step 23. |
650 // "Immediately execute the script block, | 657 // "Immediately execute the script block, |
651 // even if other scripts are already executing." | 658 // even if other scripts are already executing." |
652 // TODO(hiroshige): Merge the block into ScriptLoader::prepareScript(). | 659 // TODO(hiroshige): Merge the block into ScriptLoader::prepareScript(). |
653 DCHECK_GT(m_reentryPermit->scriptNestingLevel(), 1u); | 660 DCHECK_GT(m_reentryPermit->scriptNestingLevel(), 1u); |
654 if (m_parserBlockingScript) | 661 if (m_parserBlockingScript) |
655 m_parserBlockingScript->dispose(); | 662 m_parserBlockingScript->dispose(); |
656 m_parserBlockingScript = nullptr; | 663 m_parserBlockingScript = nullptr; |
657 ScriptSourceCode sourceCode(script->textContent(), | 664 ScriptSourceCode sourceCode(script->textContent(), |
658 documentURLForScriptExecution(m_document), | 665 documentURLForScriptExecution(m_document), |
659 scriptStartPosition); | 666 scriptStartPosition); |
660 doExecuteScript(script, sourceCode, scriptStartPosition); | 667 doExecuteScript(client, sourceCode, scriptStartPosition); |
661 } | 668 } |
662 } else { | 669 } else { |
663 // 2nd Clause of Step 23. | 670 // 2nd Clause of Step 23. |
664 requestParsingBlockingScript(script); | 671 requestParsingBlockingScript(script); |
665 } | 672 } |
666 | 673 |
667 // "Decrement the parser's script nesting level by one. | 674 // "Decrement the parser's script nesting level by one. |
668 // If the parser's script nesting level is zero, then set the parser | 675 // If the parser's script nesting level is zero, then set the parser |
669 // pause flag to false." | 676 // pause flag to false." |
670 // Implemented by ~ScriptNestingLevelIncrementer(). | 677 // Implemented by ~ScriptNestingLevelIncrementer(). |
671 | 678 |
672 // "Let the insertion point have the value of the old insertion point." | 679 // "Let the insertion point have the value of the old insertion point." |
673 // Implemented by ~InsertionPointRecord(). | 680 // Implemented by ~InsertionPointRecord(). |
674 } | 681 } |
675 } | 682 } |
676 | 683 |
677 DEFINE_TRACE(HTMLParserScriptRunner) { | 684 DEFINE_TRACE(HTMLParserScriptRunner) { |
678 visitor->trace(m_document); | 685 visitor->trace(m_document); |
679 visitor->trace(m_host); | 686 visitor->trace(m_host); |
680 visitor->trace(m_parserBlockingScript); | 687 visitor->trace(m_parserBlockingScript); |
681 visitor->trace(m_scriptsToExecuteAfterParsing); | 688 visitor->trace(m_scriptsToExecuteAfterParsing); |
682 PendingScriptClient::trace(visitor); | 689 PendingScriptClient::trace(visitor); |
683 } | 690 } |
684 | 691 |
685 } // namespace blink | 692 } // namespace blink |
OLD | NEW |