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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 // may continue to run pending scripts after the parser has | 181 // may continue to run pending scripts after the parser has |
| 182 // detached. | 182 // detached. |
| 183 } | 183 } |
| 184 | 184 |
| 185 bool HTMLParserScriptRunner::isParserBlockingScriptReady() { | 185 bool HTMLParserScriptRunner::isParserBlockingScriptReady() { |
| 186 if (!m_document->isScriptExecutionReady()) | 186 if (!m_document->isScriptExecutionReady()) |
| 187 return false; | 187 return false; |
| 188 return m_parserBlockingScript->isReady(); | 188 return m_parserBlockingScript->isReady(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 // This has two callers and corresponds to different concepts in the spec: | |
| 192 // - When called from executeParsingBlockingScripts(), this corresponds to some | |
| 193 // steps of the "Otherwise" Clause of 'An end tag whose tag name is "script"' | |
| 194 // https://html.spec.whatwg.org/#scriptEndTag | |
| 195 // - When called from executeScriptsWaitingForParsing(), this corresponds | |
| 196 // https://html.spec.whatwg.org/#execute-the-script-block | |
| 197 // and thus currently this function does more than specced. | |
| 198 // TODO(hiroshige): Make the spec and implementation consistent. | |
| 191 void HTMLParserScriptRunner::executePendingScriptAndDispatchEvent( | 199 void HTMLParserScriptRunner::executePendingScriptAndDispatchEvent( |
| 192 PendingScript* pendingScript, | 200 PendingScript* pendingScript, |
| 193 ScriptStreamer::Type pendingScriptType) { | 201 ScriptStreamer::Type pendingScriptType) { |
| 194 bool errorOccurred = false; | 202 bool errorOccurred = false; |
| 195 ScriptSourceCode sourceCode = pendingScript->getSource( | 203 ScriptSourceCode sourceCode = pendingScript->getSource( |
| 196 documentURLForScriptExecution(m_document), errorOccurred); | 204 documentURLForScriptExecution(m_document), errorOccurred); |
| 197 | 205 |
| 198 // Stop watching loads before executeScript to prevent recursion if the script | 206 // Stop watching loads before executeScript to prevent recursion if the script |
| 199 // reloads itself. | 207 // reloads itself. |
| 200 // TODO(kouhei): Consider merging this w/ pendingScript->dispose() after the | 208 // TODO(kouhei): Consider merging this w/ pendingScript->dispose() after the |
| 201 // if block. | 209 // if block. |
| 202 pendingScript->stopWatchingForLoad(); | 210 pendingScript->stopWatchingForLoad(); |
| 203 | 211 |
| 204 if (!isExecutingScript()) { | 212 if (!isExecutingScript()) { |
| 205 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); | 213 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); |
| 206 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { | 214 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { |
| 207 // The parser cannot be unblocked as a microtask requested another | 215 // The parser cannot be unblocked as a microtask requested another |
| 208 // resource | 216 // resource |
| 209 if (!m_document->isScriptExecutionReady()) | 217 if (!m_document->isScriptExecutionReady()) |
| 210 return; | 218 return; |
| 211 } | 219 } |
| 212 } | 220 } |
| 213 | 221 |
| 214 TextPosition scriptStartPosition = pendingScript->startingPosition(); | 222 TextPosition scriptStartPosition = pendingScript->startingPosition(); |
| 215 double scriptParserBlockingTime = | 223 double scriptParserBlockingTime = |
| 216 pendingScript->parserBlockingLoadStartTime(); | 224 pendingScript->parserBlockingLoadStartTime(); |
| 225 Element* element = pendingScript->element(); | |
| 226 | |
| 227 // 1. "Let the script be the pending parsing-blocking script. | |
| 228 // There is no longer a pending parsing-blocking script." | |
| 217 // Clear the pending script before possible re-entrancy from executeScript() | 229 // Clear the pending script before possible re-entrancy from executeScript() |
| 218 Element* element = pendingScript->element(); | |
| 219 pendingScript->dispose(); | 230 pendingScript->dispose(); |
| 220 | 231 |
| 221 if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element)) { | 232 if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element)) { |
| 233 // 7. "Increment the parser's script nesting level by one (it should be | |
| 234 // zero before this step, so this sets it to one)." | |
| 222 HTMLParserReentryPermit::ScriptNestingLevelIncrementer | 235 HTMLParserReentryPermit::ScriptNestingLevelIncrementer |
| 223 nestingLevelIncrementer = | 236 nestingLevelIncrementer = |
| 224 m_reentryPermit->incrementScriptNestingLevel(); | 237 m_reentryPermit->incrementScriptNestingLevel(); |
| 238 | |
| 225 IgnoreDestructiveWriteCountIncrementer | 239 IgnoreDestructiveWriteCountIncrementer |
| 226 ignoreDestructiveWriteCountIncrementer(m_document); | 240 ignoreDestructiveWriteCountIncrementer(m_document); |
| 241 | |
| 242 // 8. "Execute the script." | |
| 227 if (errorOccurred) { | 243 if (errorOccurred) { |
| 228 TRACE_EVENT_WITH_FLOW1( | 244 TRACE_EVENT_WITH_FLOW1( |
| 229 "blink", "HTMLParserScriptRunner ExecuteScriptFailed", element, | 245 "blink", "HTMLParserScriptRunner ExecuteScriptFailed", element, |
| 230 TRACE_EVENT_FLAG_FLOW_IN, "data", | 246 TRACE_EVENT_FLAG_FLOW_IN, "data", |
| 231 getTraceArgsForScriptElement(element, scriptStartPosition)); | 247 getTraceArgsForScriptElement(element, scriptStartPosition)); |
| 232 scriptLoader->dispatchErrorEvent(); | 248 scriptLoader->dispatchErrorEvent(); |
| 233 } else { | 249 } else { |
| 234 DCHECK(isExecutingScript()); | 250 DCHECK(isExecutingScript()); |
| 235 if (scriptParserBlockingTime > 0.0) { | 251 if (scriptParserBlockingTime > 0.0) { |
| 236 DocumentParserTiming::from(*m_document) | 252 DocumentParserTiming::from(*m_document) |
| 237 .recordParserBlockedOnScriptLoadDuration( | 253 .recordParserBlockedOnScriptLoadDuration( |
| 238 monotonicallyIncreasingTime() - scriptParserBlockingTime, | 254 monotonicallyIncreasingTime() - scriptParserBlockingTime, |
| 239 scriptLoader->wasCreatedDuringDocumentWrite()); | 255 scriptLoader->wasCreatedDuringDocumentWrite()); |
| 240 } | 256 } |
| 241 if (!doExecuteScript(element, sourceCode, scriptStartPosition)) { | 257 if (!doExecuteScript(element, sourceCode, scriptStartPosition)) { |
| 242 scriptLoader->dispatchErrorEvent(); | 258 scriptLoader->dispatchErrorEvent(); |
| 243 } else { | 259 } else { |
| 244 element->dispatchEvent(Event::create(EventTypeNames::load)); | 260 element->dispatchEvent(Event::create(EventTypeNames::load)); |
| 245 } | 261 } |
| 246 } | 262 } |
| 263 | |
| 264 // 9. "Decrement the parser's script nesting level by one. | |
| 265 // If the parser's script nesting level is zero | |
| 266 // (which it always should be at this point), | |
| 267 // then set the parser pause flag to false." | |
| 268 // This is implemented by scope out of ScriptNestingLevelIncrementer. | |
| 247 } | 269 } |
| 248 | 270 |
| 249 DCHECK(!isExecutingScript()); | 271 DCHECK(!isExecutingScript()); |
| 250 } | 272 } |
| 251 | 273 |
| 252 void fetchBlockedDocWriteScript(Element* script, | 274 void fetchBlockedDocWriteScript(Element* script, |
| 253 bool isParserInserted, | 275 bool isParserInserted, |
| 254 const TextPosition& scriptStartPosition) { | 276 const TextPosition& scriptStartPosition) { |
| 255 DCHECK(script); | 277 DCHECK(script); |
| 256 | 278 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 } | 360 } |
| 339 | 361 |
| 340 // If the script was blocked as part of document.write intervention, | 362 // If the script was blocked as part of document.write intervention, |
| 341 // then send an asynchronous GET request with an interventions header. | 363 // then send an asynchronous GET request with an interventions header. |
| 342 possiblyFetchBlockedDocWriteScript(pendingScript); | 364 possiblyFetchBlockedDocWriteScript(pendingScript); |
| 343 | 365 |
| 344 m_host->notifyScriptLoaded(pendingScript); | 366 m_host->notifyScriptLoaded(pendingScript); |
| 345 } | 367 } |
| 346 | 368 |
| 347 // Implements the steps for 'An end tag whose tag name is "script"' | 369 // Implements the steps for 'An end tag whose tag name is "script"' |
| 348 // http://whatwg.org/html#scriptEndTag | 370 // https://html.spec.whatwg.org/#scriptEndTag |
| 349 // Script handling lives outside the tree builder to keep each class simple. | 371 // Script handling lives outside the tree builder to keep each class simple. |
| 350 void HTMLParserScriptRunner::processScriptElement( | 372 void HTMLParserScriptRunner::processScriptElement( |
| 351 Element* scriptElement, | 373 Element* scriptElement, |
| 352 const TextPosition& scriptStartPosition) { | 374 const TextPosition& scriptStartPosition) { |
| 353 DCHECK(scriptElement); | 375 DCHECK(scriptElement); |
| 354 TRACE_EVENT1( | 376 TRACE_EVENT1( |
| 355 "blink", "HTMLParserScriptRunner::execute", "data", | 377 "blink", "HTMLParserScriptRunner::execute", "data", |
| 356 getTraceArgsForScriptElement(scriptElement, scriptStartPosition)); | 378 getTraceArgsForScriptElement(scriptElement, scriptStartPosition)); |
| 357 // FIXME: If scripting is disabled, always just return. | 379 // FIXME: If scripting is disabled, always just return. |
| 358 | 380 |
| 359 bool hadPreloadScanner = m_host->hasPreloadScanner(); | 381 bool hadPreloadScanner = m_host->hasPreloadScanner(); |
| 360 | 382 |
| 383 // Initial steps of 'An end tag whose tag name is "script"'. | |
| 361 // Try to execute the script given to us. | 384 // Try to execute the script given to us. |
| 362 processScriptElementInternal(scriptElement, scriptStartPosition); | 385 processScriptElementInternal(scriptElement, scriptStartPosition); |
| 363 | 386 |
| 387 // "At this stage, if there is a pending parsing-blocking script, then:" | |
| 364 if (hasParserBlockingScript()) { | 388 if (hasParserBlockingScript()) { |
| 389 // - "If the script nesting level is not zero:" | |
| 365 if (isExecutingScript()) { | 390 if (isExecutingScript()) { |
| 391 // "Set the parser pause flag to true, and abort the processing of any | |
| 392 // nested invocations of the tokenizer, yielding control back to the | |
| 393 // caller. (Tokenization will resume when the caller returns to the | |
| 394 // "outer" tree construction stage.)" | |
| 395 // TODO(hiroshige): set the parser pause flag to true here. | |
| 396 | |
| 366 // Unwind to the outermost HTMLParserScriptRunner::processScriptElement | 397 // Unwind to the outermost HTMLParserScriptRunner::processScriptElement |
| 367 // before continuing parsing. | 398 // before continuing parsing. |
| 368 return; | 399 return; |
| 369 } | 400 } |
| 370 | 401 |
| 402 // - "Otherwise": | |
| 403 | |
| 371 traceParserBlockingScript(m_parserBlockingScript.get(), | 404 traceParserBlockingScript(m_parserBlockingScript.get(), |
| 372 !m_document->isScriptExecutionReady()); | 405 !m_document->isScriptExecutionReady()); |
| 373 m_parserBlockingScript->markParserBlockingLoadStartTime(); | 406 m_parserBlockingScript->markParserBlockingLoadStartTime(); |
| 374 | 407 |
| 375 // If preload scanner got created, it is missing the source after the | 408 // If preload scanner got created, it is missing the source after the |
| 376 // current insertion point. Append it and scan. | 409 // current insertion point. Append it and scan. |
| 377 if (!hadPreloadScanner && m_host->hasPreloadScanner()) | 410 if (!hadPreloadScanner && m_host->hasPreloadScanner()) |
| 378 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); | 411 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); |
| 412 | |
| 379 executeParsingBlockingScripts(); | 413 executeParsingBlockingScripts(); |
| 380 } | 414 } |
| 381 } | 415 } |
| 382 | 416 |
| 383 bool HTMLParserScriptRunner::hasParserBlockingScript() const { | 417 bool HTMLParserScriptRunner::hasParserBlockingScript() const { |
| 384 return !!m_parserBlockingScript->element(); | 418 return !!m_parserBlockingScript->element(); |
| 385 } | 419 } |
| 386 | 420 |
| 421 // Implements the "Otherwise" Clause of 'An end tag whose tag name is "script"' | |
|
dominicc (has gone to gerrit)
2017/02/16 08:41:00
I would make this more succinct by dropping "imple
hiroshige
2017/02/20 23:56:40
Done.
| |
| 422 // https://html.spec.whatwg.org/#scriptEndTag | |
| 387 void HTMLParserScriptRunner::executeParsingBlockingScripts() { | 423 void HTMLParserScriptRunner::executeParsingBlockingScripts() { |
| 424 // 3. "If (1) the parser's Document has a style sheet that is blocking scripts | |
| 425 // or (2) the script's "ready to be parser-executed" flag is not set: | |
| 426 // spin the event loop | |
| 427 // until the parser's Document has no style sheet that is blocking scripts | |
| 428 // and the script's "ready to be parser-executed" flag is set." | |
| 429 // These conditions correspond to isParserBlockingScriptReady() and | |
|
dominicc (has gone to gerrit)
2017/02/16 08:41:00
Great comment; thank you so much for doing this.
hiroshige
2017/02/20 23:56:40
Done.
| |
| 430 // if it is false, executeParsingBlockingScripts() will be called later | |
| 431 // when isParserBlockingScriptReady() becomes true: | |
| 432 // (1) from HTMLParserScriptRunner::executeScriptsWaitingForResources(), or | |
| 433 // (2) from HTMLParserScriptRunner::executeScriptsWaitingForLoad(). | |
| 388 while (hasParserBlockingScript() && isParserBlockingScriptReady()) { | 434 while (hasParserBlockingScript() && isParserBlockingScriptReady()) { |
| 389 DCHECK(m_document); | 435 DCHECK(m_document); |
| 390 DCHECK(!isExecutingScript()); | 436 DCHECK(!isExecutingScript()); |
| 391 DCHECK(m_document->isScriptExecutionReady()); | 437 DCHECK(m_document->isScriptExecutionReady()); |
| 392 | 438 |
| 439 // 6. "Let the insertion point be just before the next input character." | |
| 393 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 440 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
| 441 | |
| 442 // 1., 7.--9. | |
| 394 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), | 443 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), |
| 395 ScriptStreamer::ParsingBlocking); | 444 ScriptStreamer::ParsingBlocking); |
| 445 | |
| 446 // 10. "Let the insertion point be undefined again." | |
| 447 // Implemented as scope out of InsertionPointRecord. | |
|
dominicc (has gone to gerrit)
2017/02/16 08:41:00
"scope out of" is a bit awkward. Maybe say somethi
hiroshige
2017/02/20 23:56:40
Done.
| |
| 448 | |
| 449 // 11. "If there is once again a pending parsing-blocking script, then | |
| 450 // repeat these steps from step 1." | |
| 396 } | 451 } |
| 397 } | 452 } |
| 398 | 453 |
| 399 void HTMLParserScriptRunner::executeScriptsWaitingForLoad( | 454 void HTMLParserScriptRunner::executeScriptsWaitingForLoad( |
| 400 PendingScript* pendingScript) { | 455 PendingScript* pendingScript) { |
| 401 TRACE_EVENT0("blink", "HTMLParserScriptRunner::executeScriptsWaitingForLoad"); | 456 TRACE_EVENT0("blink", "HTMLParserScriptRunner::executeScriptsWaitingForLoad"); |
| 402 DCHECK(!isExecutingScript()); | 457 DCHECK(!isExecutingScript()); |
| 403 DCHECK(hasParserBlockingScript()); | 458 DCHECK(hasParserBlockingScript()); |
| 404 DCHECK_EQ(pendingScript, m_parserBlockingScript); | 459 DCHECK_EQ(pendingScript, m_parserBlockingScript); |
| 405 DCHECK(m_parserBlockingScript->isReady()); | 460 DCHECK(m_parserBlockingScript->isReady()); |
| 406 executeParsingBlockingScripts(); | 461 executeParsingBlockingScripts(); |
| 407 } | 462 } |
| 408 | 463 |
| 409 void HTMLParserScriptRunner::executeScriptsWaitingForResources() { | 464 void HTMLParserScriptRunner::executeScriptsWaitingForResources() { |
| 410 TRACE_EVENT0("blink", | 465 TRACE_EVENT0("blink", |
| 411 "HTMLParserScriptRunner::executeScriptsWaitingForResources"); | 466 "HTMLParserScriptRunner::executeScriptsWaitingForResources"); |
| 412 DCHECK(m_document); | 467 DCHECK(m_document); |
| 413 DCHECK(!isExecutingScript()); | 468 DCHECK(!isExecutingScript()); |
| 414 DCHECK(m_document->isScriptExecutionReady()); | 469 DCHECK(m_document->isScriptExecutionReady()); |
| 415 executeParsingBlockingScripts(); | 470 executeParsingBlockingScripts(); |
| 416 } | 471 } |
| 417 | 472 |
| 473 // Step 3 of https://html.spec.whatwg.org/#the-end: | |
| 474 // "If the list of scripts that will execute when the document has | |
| 475 // finished parsing is not empty, run these substeps:" | |
| 418 bool HTMLParserScriptRunner::executeScriptsWaitingForParsing() { | 476 bool HTMLParserScriptRunner::executeScriptsWaitingForParsing() { |
| 419 TRACE_EVENT0("blink", | 477 TRACE_EVENT0("blink", |
| 420 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); | 478 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); |
| 479 | |
| 421 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 480 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
| 422 DCHECK(!isExecutingScript()); | 481 DCHECK(!isExecutingScript()); |
| 423 DCHECK(!hasParserBlockingScript()); | 482 DCHECK(!hasParserBlockingScript()); |
| 424 DCHECK(m_scriptsToExecuteAfterParsing.first()->resource()); | 483 DCHECK(m_scriptsToExecuteAfterParsing.first()->resource()); |
| 484 | |
| 485 // 1. "Spin the event loop until the first script in the list of scripts | |
| 486 // that will execute when the document has finished parsing | |
| 487 // has its "ready to be parser-executed" flag set and | |
| 488 // the parser's Document has no style sheet that is blocking scripts." | |
| 489 // TODO(hiroshige): Is the latter part checked anywhere? | |
| 425 if (!m_scriptsToExecuteAfterParsing.first()->isReady()) { | 490 if (!m_scriptsToExecuteAfterParsing.first()->isReady()) { |
| 426 m_scriptsToExecuteAfterParsing.first()->watchForLoad(this); | 491 m_scriptsToExecuteAfterParsing.first()->watchForLoad(this); |
| 427 traceParserBlockingScript(m_scriptsToExecuteAfterParsing.first().get(), | 492 traceParserBlockingScript(m_scriptsToExecuteAfterParsing.first().get(), |
| 428 !m_document->isScriptExecutionReady()); | 493 !m_document->isScriptExecutionReady()); |
| 429 m_scriptsToExecuteAfterParsing.first()->markParserBlockingLoadStartTime(); | 494 m_scriptsToExecuteAfterParsing.first()->markParserBlockingLoadStartTime(); |
| 430 return false; | 495 return false; |
| 431 } | 496 } |
| 497 | |
| 498 // 3. "Remove the first script element from the list of scripts that will | |
| 499 // execute when the document has finished parsing (i.e. shift out the | |
| 500 // first entry in the list)." | |
| 432 PendingScript* first = m_scriptsToExecuteAfterParsing.takeFirst(); | 501 PendingScript* first = m_scriptsToExecuteAfterParsing.takeFirst(); |
| 502 | |
| 503 // 2. "Execute the first script in the list of scripts that will execute | |
| 504 // when the document has finished parsing." | |
| 433 executePendingScriptAndDispatchEvent(first, ScriptStreamer::Deferred); | 505 executePendingScriptAndDispatchEvent(first, ScriptStreamer::Deferred); |
| 506 | |
| 434 // FIXME: What is this m_document check for? | 507 // FIXME: What is this m_document check for? |
| 435 if (!m_document) | 508 if (!m_document) |
| 436 return false; | 509 return false; |
| 510 | |
| 511 // 4. "If the list of scripts that will execute when the document has | |
| 512 // finished parsing is still not empty, repeat these substeps again | |
| 513 // from substep 1." | |
| 437 } | 514 } |
| 438 return true; | 515 return true; |
| 439 } | 516 } |
| 440 | 517 |
| 441 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script | 518 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script |
| 442 void HTMLParserScriptRunner::requestParsingBlockingScript(Element* element) { | 519 void HTMLParserScriptRunner::requestParsingBlockingScript(Element* element) { |
| 443 // "The element is the pending parsing-blocking script of the Document of | 520 // "The element is the pending parsing-blocking script of the Document of |
| 444 // the parser that created the element. | 521 // the parser that created the element. |
| 445 // (There can only be one such script per Document at a time.)" | 522 // (There can only be one such script per Document at a time.)" |
| 446 if (!requestPendingScript(m_parserBlockingScript.get(), element)) | 523 if (!requestPendingScript(m_parserBlockingScript.get(), element)) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 ScriptResource* resource = toScriptLoaderIfPossible(script)->resource(); | 575 ScriptResource* resource = toScriptLoaderIfPossible(script)->resource(); |
| 499 if (!resource) { | 576 if (!resource) { |
| 500 DVLOG(1) << "Not implemented."; // Dispatch error event. | 577 DVLOG(1) << "Not implemented."; // Dispatch error event. |
| 501 return false; | 578 return false; |
| 502 } | 579 } |
| 503 pendingScript->setScriptResource(resource); | 580 pendingScript->setScriptResource(resource); |
| 504 return true; | 581 return true; |
| 505 } | 582 } |
| 506 | 583 |
| 507 // Implements the initial steps for 'An end tag whose tag name is "script"' | 584 // Implements the initial steps for 'An end tag whose tag name is "script"' |
| 508 // http://whatwg.org/html#scriptEndTag | 585 // https://html.spec.whatwg.org/#scriptEndTag |
| 509 void HTMLParserScriptRunner::processScriptElementInternal( | 586 void HTMLParserScriptRunner::processScriptElementInternal( |
| 510 Element* script, | 587 Element* script, |
| 511 const TextPosition& scriptStartPosition) { | 588 const TextPosition& scriptStartPosition) { |
| 512 DCHECK(m_document); | 589 DCHECK(m_document); |
| 513 DCHECK(!hasParserBlockingScript()); | 590 DCHECK(!hasParserBlockingScript()); |
| 514 { | 591 { |
| 515 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(script); | 592 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(script); |
| 516 | 593 |
| 517 // This contains both a DCHECK and a null check since we should not | 594 // This contains both a DCHECK and a null check since we should not |
| 518 // be getting into the case of a null script element, but seem to be from | 595 // be getting into the case of a null script element, but seem to be from |
| 519 // time to time. The assertion is left in to help find those cases and | 596 // time to time. The assertion is left in to help find those cases and |
| 520 // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. | 597 // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. |
| 521 DCHECK(scriptLoader); | 598 DCHECK(scriptLoader); |
| 522 if (!scriptLoader) | 599 if (!scriptLoader) |
| 523 return; | 600 return; |
| 524 | 601 |
| 525 DCHECK(scriptLoader->isParserInserted()); | 602 DCHECK(scriptLoader->isParserInserted()); |
| 526 | 603 |
| 527 if (!isExecutingScript()) | 604 if (!isExecutingScript()) |
| 528 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); | 605 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); |
| 529 | 606 |
| 607 // "Let the old insertion point have the same value as the current | |
| 608 // insertion point. | |
| 609 // Let the insertion point be just before the next input character." | |
| 530 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 610 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
| 611 | |
| 612 // "Increment the parser's script nesting level by one." | |
| 531 HTMLParserReentryPermit::ScriptNestingLevelIncrementer | 613 HTMLParserReentryPermit::ScriptNestingLevelIncrementer |
| 532 nestingLevelIncrementer = | 614 nestingLevelIncrementer = |
| 533 m_reentryPermit->incrementScriptNestingLevel(); | 615 m_reentryPermit->incrementScriptNestingLevel(); |
| 534 | 616 |
| 617 // "Prepare the script. This might cause some script to execute, which | |
| 618 // might cause new characters to be inserted into the tokenizer, and | |
| 619 // might cause the tokenizer to output more tokens, resulting in a | |
| 620 // reentrant invocation of the parser." | |
| 535 scriptLoader->prepareScript(scriptStartPosition); | 621 scriptLoader->prepareScript(scriptStartPosition); |
| 536 | 622 |
| 537 // A part of Step 23 of https://html.spec.whatwg.org/#prepare-a-script: | 623 // A part of Step 23 of https://html.spec.whatwg.org/#prepare-a-script: |
| 538 if (!scriptLoader->willBeParserExecuted()) | 624 if (!scriptLoader->willBeParserExecuted()) |
| 539 return; | 625 return; |
| 540 | 626 |
| 541 if (scriptLoader->willExecuteWhenDocumentFinishedParsing()) { | 627 if (scriptLoader->willExecuteWhenDocumentFinishedParsing()) { |
| 542 // 1st Clause of Step 23. | 628 // 1st Clause of Step 23. |
| 543 requestDeferredScript(script); | 629 requestDeferredScript(script); |
| 544 } else if (scriptLoader->readyToBeParserExecuted()) { | 630 } else if (scriptLoader->readyToBeParserExecuted()) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 560 m_parserBlockingScript->dispose(); | 646 m_parserBlockingScript->dispose(); |
| 561 ScriptSourceCode sourceCode(script->textContent(), | 647 ScriptSourceCode sourceCode(script->textContent(), |
| 562 documentURLForScriptExecution(m_document), | 648 documentURLForScriptExecution(m_document), |
| 563 scriptStartPosition); | 649 scriptStartPosition); |
| 564 doExecuteScript(script, sourceCode, scriptStartPosition); | 650 doExecuteScript(script, sourceCode, scriptStartPosition); |
| 565 } | 651 } |
| 566 } else { | 652 } else { |
| 567 // 2nd Clause of Step 23. | 653 // 2nd Clause of Step 23. |
| 568 requestParsingBlockingScript(script); | 654 requestParsingBlockingScript(script); |
| 569 } | 655 } |
| 656 | |
| 657 // "Decrement the parser's script nesting level by one. | |
| 658 // If the parser's script nesting level is zero, then set the parser | |
| 659 // pause flag to false." | |
| 660 // Implemented by scope out of ScriptNestingLevelIncrementer. | |
| 661 | |
| 662 // "Let the insertion point have the value of the old insertion point." | |
| 663 // Implemented by scope out of InsertionPointRecord. | |
| 570 } | 664 } |
| 571 } | 665 } |
| 572 | 666 |
| 573 DEFINE_TRACE(HTMLParserScriptRunner) { | 667 DEFINE_TRACE(HTMLParserScriptRunner) { |
| 574 visitor->trace(m_document); | 668 visitor->trace(m_document); |
| 575 visitor->trace(m_host); | 669 visitor->trace(m_host); |
| 576 visitor->trace(m_parserBlockingScript); | 670 visitor->trace(m_parserBlockingScript); |
| 577 visitor->trace(m_scriptsToExecuteAfterParsing); | 671 visitor->trace(m_scriptsToExecuteAfterParsing); |
| 578 PendingScriptClient::trace(visitor); | 672 PendingScriptClient::trace(visitor); |
| 579 } | 673 } |
| 580 | 674 |
| 581 } // namespace blink | 675 } // namespace blink |
| OLD | NEW |