Chromium Code Reviews| 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 |