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 ~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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 return; | 359 return; |
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 // 'An end tag whose tag name is "script"' |
348 // http://whatwg.org/html#scriptEndTag | 370 // https://html.spec.whatwg.org/#scriptEndTag |
| 371 // |
349 // Script handling lives outside the tree builder to keep each class simple. | 372 // Script handling lives outside the tree builder to keep each class simple. |
350 void HTMLParserScriptRunner::processScriptElement( | 373 void HTMLParserScriptRunner::processScriptElement( |
351 Element* scriptElement, | 374 Element* scriptElement, |
352 const TextPosition& scriptStartPosition) { | 375 const TextPosition& scriptStartPosition) { |
353 DCHECK(scriptElement); | 376 DCHECK(scriptElement); |
354 TRACE_EVENT1( | 377 TRACE_EVENT1( |
355 "blink", "HTMLParserScriptRunner::execute", "data", | 378 "blink", "HTMLParserScriptRunner::execute", "data", |
356 getTraceArgsForScriptElement(scriptElement, scriptStartPosition)); | 379 getTraceArgsForScriptElement(scriptElement, scriptStartPosition)); |
357 // FIXME: If scripting is disabled, always just return. | 380 // FIXME: If scripting is disabled, always just return. |
358 | 381 |
359 bool hadPreloadScanner = m_host->hasPreloadScanner(); | 382 bool hadPreloadScanner = m_host->hasPreloadScanner(); |
360 | 383 |
| 384 // Initial steps of 'An end tag whose tag name is "script"'. |
361 // Try to execute the script given to us. | 385 // Try to execute the script given to us. |
362 processScriptElementInternal(scriptElement, scriptStartPosition); | 386 processScriptElementInternal(scriptElement, scriptStartPosition); |
363 | 387 |
| 388 // "At this stage, if there is a pending parsing-blocking script, then:" |
364 if (hasParserBlockingScript()) { | 389 if (hasParserBlockingScript()) { |
| 390 // - "If the script nesting level is not zero:" |
365 if (isExecutingScript()) { | 391 if (isExecutingScript()) { |
| 392 // "Set the parser pause flag to true, and abort the processing of any |
| 393 // nested invocations of the tokenizer, yielding control back to the |
| 394 // caller. (Tokenization will resume when the caller returns to the |
| 395 // "outer" tree construction stage.)" |
| 396 // TODO(hiroshige): set the parser pause flag to true here. |
| 397 |
366 // Unwind to the outermost HTMLParserScriptRunner::processScriptElement | 398 // Unwind to the outermost HTMLParserScriptRunner::processScriptElement |
367 // before continuing parsing. | 399 // before continuing parsing. |
368 return; | 400 return; |
369 } | 401 } |
370 | 402 |
| 403 // - "Otherwise": |
| 404 |
371 traceParserBlockingScript(m_parserBlockingScript.get(), | 405 traceParserBlockingScript(m_parserBlockingScript.get(), |
372 !m_document->isScriptExecutionReady()); | 406 !m_document->isScriptExecutionReady()); |
373 m_parserBlockingScript->markParserBlockingLoadStartTime(); | 407 m_parserBlockingScript->markParserBlockingLoadStartTime(); |
374 | 408 |
375 // If preload scanner got created, it is missing the source after the | 409 // If preload scanner got created, it is missing the source after the |
376 // current insertion point. Append it and scan. | 410 // current insertion point. Append it and scan. |
377 if (!hadPreloadScanner && m_host->hasPreloadScanner()) | 411 if (!hadPreloadScanner && m_host->hasPreloadScanner()) |
378 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); | 412 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); |
| 413 |
379 executeParsingBlockingScripts(); | 414 executeParsingBlockingScripts(); |
380 } | 415 } |
381 } | 416 } |
382 | 417 |
383 bool HTMLParserScriptRunner::hasParserBlockingScript() const { | 418 bool HTMLParserScriptRunner::hasParserBlockingScript() const { |
384 return !!m_parserBlockingScript->element(); | 419 return !!m_parserBlockingScript->element(); |
385 } | 420 } |
386 | 421 |
| 422 // The "Otherwise" Clause of 'An end tag whose tag name is "script"' |
| 423 // https://html.spec.whatwg.org/#scriptEndTag |
387 void HTMLParserScriptRunner::executeParsingBlockingScripts() { | 424 void HTMLParserScriptRunner::executeParsingBlockingScripts() { |
| 425 // 3. "If (1) the parser's Document has a style sheet that is blocking scripts |
| 426 // or (2) the script's "ready to be parser-executed" flag is not set: |
| 427 // spin the event loop |
| 428 // until the parser's Document has no style sheet that is blocking scripts |
| 429 // and the script's "ready to be parser-executed" flag is set." |
| 430 // |
| 431 // These conditions correspond to isParserBlockingScriptReady() and |
| 432 // if it is false, executeParsingBlockingScripts() will be called later |
| 433 // when isParserBlockingScriptReady() becomes true: |
| 434 // (1) from HTMLParserScriptRunner::executeScriptsWaitingForResources(), or |
| 435 // (2) from HTMLParserScriptRunner::executeScriptsWaitingForLoad(). |
388 while (hasParserBlockingScript() && isParserBlockingScriptReady()) { | 436 while (hasParserBlockingScript() && isParserBlockingScriptReady()) { |
389 DCHECK(m_document); | 437 DCHECK(m_document); |
390 DCHECK(!isExecutingScript()); | 438 DCHECK(!isExecutingScript()); |
391 DCHECK(m_document->isScriptExecutionReady()); | 439 DCHECK(m_document->isScriptExecutionReady()); |
392 | 440 |
| 441 // 6. "Let the insertion point be just before the next input character." |
393 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 442 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
| 443 |
| 444 // 1., 7.--9. |
394 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), | 445 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), |
395 ScriptStreamer::ParsingBlocking); | 446 ScriptStreamer::ParsingBlocking); |
| 447 |
| 448 // 10. "Let the insertion point be undefined again." |
| 449 // Implemented as ~InsertionPointRecord(). |
| 450 |
| 451 // 11. "If there is once again a pending parsing-blocking script, then |
| 452 // repeat these steps from step 1." |
396 } | 453 } |
397 } | 454 } |
398 | 455 |
399 void HTMLParserScriptRunner::executeScriptsWaitingForLoad( | 456 void HTMLParserScriptRunner::executeScriptsWaitingForLoad( |
400 PendingScript* pendingScript) { | 457 PendingScript* pendingScript) { |
401 TRACE_EVENT0("blink", "HTMLParserScriptRunner::executeScriptsWaitingForLoad"); | 458 TRACE_EVENT0("blink", "HTMLParserScriptRunner::executeScriptsWaitingForLoad"); |
402 DCHECK(!isExecutingScript()); | 459 DCHECK(!isExecutingScript()); |
403 DCHECK(hasParserBlockingScript()); | 460 DCHECK(hasParserBlockingScript()); |
404 DCHECK_EQ(pendingScript, m_parserBlockingScript); | 461 DCHECK_EQ(pendingScript, m_parserBlockingScript); |
405 DCHECK(m_parserBlockingScript->isReady()); | 462 DCHECK(m_parserBlockingScript->isReady()); |
406 executeParsingBlockingScripts(); | 463 executeParsingBlockingScripts(); |
407 } | 464 } |
408 | 465 |
409 void HTMLParserScriptRunner::executeScriptsWaitingForResources() { | 466 void HTMLParserScriptRunner::executeScriptsWaitingForResources() { |
410 TRACE_EVENT0("blink", | 467 TRACE_EVENT0("blink", |
411 "HTMLParserScriptRunner::executeScriptsWaitingForResources"); | 468 "HTMLParserScriptRunner::executeScriptsWaitingForResources"); |
412 DCHECK(m_document); | 469 DCHECK(m_document); |
413 DCHECK(!isExecutingScript()); | 470 DCHECK(!isExecutingScript()); |
414 DCHECK(m_document->isScriptExecutionReady()); | 471 DCHECK(m_document->isScriptExecutionReady()); |
415 executeParsingBlockingScripts(); | 472 executeParsingBlockingScripts(); |
416 } | 473 } |
417 | 474 |
| 475 // Step 3 of https://html.spec.whatwg.org/#the-end: |
| 476 // "If the list of scripts that will execute when the document has |
| 477 // finished parsing is not empty, run these substeps:" |
418 bool HTMLParserScriptRunner::executeScriptsWaitingForParsing() { | 478 bool HTMLParserScriptRunner::executeScriptsWaitingForParsing() { |
419 TRACE_EVENT0("blink", | 479 TRACE_EVENT0("blink", |
420 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); | 480 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); |
| 481 |
421 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 482 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
422 DCHECK(!isExecutingScript()); | 483 DCHECK(!isExecutingScript()); |
423 DCHECK(!hasParserBlockingScript()); | 484 DCHECK(!hasParserBlockingScript()); |
424 DCHECK(m_scriptsToExecuteAfterParsing.first()->resource()); | 485 DCHECK(m_scriptsToExecuteAfterParsing.first()->resource()); |
| 486 |
| 487 // 1. "Spin the event loop until the first script in the list of scripts |
| 488 // that will execute when the document has finished parsing |
| 489 // has its "ready to be parser-executed" flag set and |
| 490 // the parser's Document has no style sheet that is blocking scripts." |
| 491 // TODO(hiroshige): Is the latter part checked anywhere? |
425 if (!m_scriptsToExecuteAfterParsing.first()->isReady()) { | 492 if (!m_scriptsToExecuteAfterParsing.first()->isReady()) { |
426 m_scriptsToExecuteAfterParsing.first()->watchForLoad(this); | 493 m_scriptsToExecuteAfterParsing.first()->watchForLoad(this); |
427 traceParserBlockingScript(m_scriptsToExecuteAfterParsing.first().get(), | 494 traceParserBlockingScript(m_scriptsToExecuteAfterParsing.first().get(), |
428 !m_document->isScriptExecutionReady()); | 495 !m_document->isScriptExecutionReady()); |
429 m_scriptsToExecuteAfterParsing.first()->markParserBlockingLoadStartTime(); | 496 m_scriptsToExecuteAfterParsing.first()->markParserBlockingLoadStartTime(); |
430 return false; | 497 return false; |
431 } | 498 } |
| 499 |
| 500 // 3. "Remove the first script element from the list of scripts that will |
| 501 // execute when the document has finished parsing (i.e. shift out the |
| 502 // first entry in the list)." |
432 PendingScript* first = m_scriptsToExecuteAfterParsing.takeFirst(); | 503 PendingScript* first = m_scriptsToExecuteAfterParsing.takeFirst(); |
| 504 |
| 505 // 2. "Execute the first script in the list of scripts that will execute |
| 506 // when the document has finished parsing." |
433 executePendingScriptAndDispatchEvent(first, ScriptStreamer::Deferred); | 507 executePendingScriptAndDispatchEvent(first, ScriptStreamer::Deferred); |
| 508 |
434 // FIXME: What is this m_document check for? | 509 // FIXME: What is this m_document check for? |
435 if (!m_document) | 510 if (!m_document) |
436 return false; | 511 return false; |
| 512 |
| 513 // 4. "If the list of scripts that will execute when the document has |
| 514 // finished parsing is still not empty, repeat these substeps again |
| 515 // from substep 1." |
437 } | 516 } |
438 return true; | 517 return true; |
439 } | 518 } |
440 | 519 |
441 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script | 520 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script |
442 void HTMLParserScriptRunner::requestParsingBlockingScript(Element* element) { | 521 void HTMLParserScriptRunner::requestParsingBlockingScript(Element* element) { |
443 // "The element is the pending parsing-blocking script of the Document of | 522 // "The element is the pending parsing-blocking script of the Document of |
444 // the parser that created the element. | 523 // the parser that created the element. |
445 // (There can only be one such script per Document at a time.)" | 524 // (There can only be one such script per Document at a time.)" |
446 if (!requestPendingScript(m_parserBlockingScript.get(), element)) | 525 if (!requestPendingScript(m_parserBlockingScript.get(), element)) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 // This should correctly return 0 for empty or invalid srcValues. | 576 // This should correctly return 0 for empty or invalid srcValues. |
498 ScriptResource* resource = toScriptLoaderIfPossible(script)->resource(); | 577 ScriptResource* resource = toScriptLoaderIfPossible(script)->resource(); |
499 if (!resource) { | 578 if (!resource) { |
500 DVLOG(1) << "Not implemented."; // Dispatch error event. | 579 DVLOG(1) << "Not implemented."; // Dispatch error event. |
501 return false; | 580 return false; |
502 } | 581 } |
503 pendingScript->setScriptResource(resource); | 582 pendingScript->setScriptResource(resource); |
504 return true; | 583 return true; |
505 } | 584 } |
506 | 585 |
507 // Implements the initial steps for 'An end tag whose tag name is "script"' | 586 // The initial steps for 'An end tag whose tag name is "script"' |
508 // http://whatwg.org/html#scriptEndTag | 587 // https://html.spec.whatwg.org/#scriptEndTag |
509 void HTMLParserScriptRunner::processScriptElementInternal( | 588 void HTMLParserScriptRunner::processScriptElementInternal( |
510 Element* script, | 589 Element* script, |
511 const TextPosition& scriptStartPosition) { | 590 const TextPosition& scriptStartPosition) { |
512 DCHECK(m_document); | 591 DCHECK(m_document); |
513 DCHECK(!hasParserBlockingScript()); | 592 DCHECK(!hasParserBlockingScript()); |
514 { | 593 { |
515 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(script); | 594 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(script); |
516 | 595 |
517 // This contains both a DCHECK and a null check since we should not | 596 // 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 | 597 // 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 | 598 // 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>. | 599 // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. |
521 DCHECK(scriptLoader); | 600 DCHECK(scriptLoader); |
522 if (!scriptLoader) | 601 if (!scriptLoader) |
523 return; | 602 return; |
524 | 603 |
525 DCHECK(scriptLoader->isParserInserted()); | 604 DCHECK(scriptLoader->isParserInserted()); |
526 | 605 |
527 if (!isExecutingScript()) | 606 if (!isExecutingScript()) |
528 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); | 607 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); |
529 | 608 |
| 609 // "Let the old insertion point have the same value as the current |
| 610 // insertion point. |
| 611 // Let the insertion point be just before the next input character." |
530 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 612 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
| 613 |
| 614 // "Increment the parser's script nesting level by one." |
531 HTMLParserReentryPermit::ScriptNestingLevelIncrementer | 615 HTMLParserReentryPermit::ScriptNestingLevelIncrementer |
532 nestingLevelIncrementer = | 616 nestingLevelIncrementer = |
533 m_reentryPermit->incrementScriptNestingLevel(); | 617 m_reentryPermit->incrementScriptNestingLevel(); |
534 | 618 |
| 619 // "Prepare the script. This might cause some script to execute, which |
| 620 // might cause new characters to be inserted into the tokenizer, and |
| 621 // might cause the tokenizer to output more tokens, resulting in a |
| 622 // reentrant invocation of the parser." |
535 scriptLoader->prepareScript(scriptStartPosition); | 623 scriptLoader->prepareScript(scriptStartPosition); |
536 | 624 |
537 // A part of Step 23 of https://html.spec.whatwg.org/#prepare-a-script: | 625 // A part of Step 23 of https://html.spec.whatwg.org/#prepare-a-script: |
538 if (!scriptLoader->willBeParserExecuted()) | 626 if (!scriptLoader->willBeParserExecuted()) |
539 return; | 627 return; |
540 | 628 |
541 if (scriptLoader->willExecuteWhenDocumentFinishedParsing()) { | 629 if (scriptLoader->willExecuteWhenDocumentFinishedParsing()) { |
542 // 1st Clause of Step 23. | 630 // 1st Clause of Step 23. |
543 requestDeferredScript(script); | 631 requestDeferredScript(script); |
544 } else if (scriptLoader->readyToBeParserExecuted()) { | 632 } else if (scriptLoader->readyToBeParserExecuted()) { |
(...skipping 15 matching lines...) Expand all Loading... |
560 m_parserBlockingScript->dispose(); | 648 m_parserBlockingScript->dispose(); |
561 ScriptSourceCode sourceCode(script->textContent(), | 649 ScriptSourceCode sourceCode(script->textContent(), |
562 documentURLForScriptExecution(m_document), | 650 documentURLForScriptExecution(m_document), |
563 scriptStartPosition); | 651 scriptStartPosition); |
564 doExecuteScript(script, sourceCode, scriptStartPosition); | 652 doExecuteScript(script, sourceCode, scriptStartPosition); |
565 } | 653 } |
566 } else { | 654 } else { |
567 // 2nd Clause of Step 23. | 655 // 2nd Clause of Step 23. |
568 requestParsingBlockingScript(script); | 656 requestParsingBlockingScript(script); |
569 } | 657 } |
| 658 |
| 659 // "Decrement the parser's script nesting level by one. |
| 660 // If the parser's script nesting level is zero, then set the parser |
| 661 // pause flag to false." |
| 662 // Implemented by ~ScriptNestingLevelIncrementer(). |
| 663 |
| 664 // "Let the insertion point have the value of the old insertion point." |
| 665 // Implemented by ~InsertionPointRecord(). |
570 } | 666 } |
571 } | 667 } |
572 | 668 |
573 DEFINE_TRACE(HTMLParserScriptRunner) { | 669 DEFINE_TRACE(HTMLParserScriptRunner) { |
574 visitor->trace(m_document); | 670 visitor->trace(m_document); |
575 visitor->trace(m_host); | 671 visitor->trace(m_host); |
576 visitor->trace(m_parserBlockingScript); | 672 visitor->trace(m_parserBlockingScript); |
577 visitor->trace(m_scriptsToExecuteAfterParsing); | 673 visitor->trace(m_scriptsToExecuteAfterParsing); |
578 PendingScriptClient::trace(visitor); | 674 PendingScriptClient::trace(visitor); |
579 } | 675 } |
580 | 676 |
581 } // namespace blink | 677 } // namespace blink |
OLD | NEW |