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

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

Issue 2238543002: Instrument parser blocking script execution time. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv ed. 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv ed.
6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> 6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 10 matching lines...) Expand all
21 * Boston, MA 02110-1301, USA. 21 * Boston, MA 02110-1301, USA.
22 */ 22 */
23 23
24 #include "core/dom/ScriptLoader.h" 24 #include "core/dom/ScriptLoader.h"
25 25
26 #include "bindings/core/v8/ScriptController.h" 26 #include "bindings/core/v8/ScriptController.h"
27 #include "bindings/core/v8/ScriptSourceCode.h" 27 #include "bindings/core/v8/ScriptSourceCode.h"
28 #include "core/HTMLNames.h" 28 #include "core/HTMLNames.h"
29 #include "core/SVGNames.h" 29 #include "core/SVGNames.h"
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/dom/DocumentParserTiming.h"
31 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" 32 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
32 #include "core/dom/ScriptLoaderClient.h" 33 #include "core/dom/ScriptLoaderClient.h"
33 #include "core/dom/ScriptRunner.h" 34 #include "core/dom/ScriptRunner.h"
34 #include "core/dom/ScriptableDocumentParser.h" 35 #include "core/dom/ScriptableDocumentParser.h"
35 #include "core/dom/Text.h" 36 #include "core/dom/Text.h"
36 #include "core/events/Event.h" 37 #include "core/events/Event.h"
37 #include "core/fetch/AccessControlStatus.h" 38 #include "core/fetch/AccessControlStatus.h"
38 #include "core/fetch/FetchRequest.h" 39 #include "core/fetch/FetchRequest.h"
39 #include "core/fetch/ResourceFetcher.h" 40 #include "core/fetch/ResourceFetcher.h"
40 #include "core/fetch/ScriptResource.h" 41 #include "core/fetch/ScriptResource.h"
(...skipping 18 matching lines...) Expand all
59 60
60 ScriptLoader::ScriptLoader(Element* element, bool parserInserted, bool alreadySt arted, bool createdDuringDocumentWrite) 61 ScriptLoader::ScriptLoader(Element* element, bool parserInserted, bool alreadySt arted, bool createdDuringDocumentWrite)
61 : m_element(element) 62 : m_element(element)
62 , m_startLineNumber(WTF::OrdinalNumber::beforeFirst()) 63 , m_startLineNumber(WTF::OrdinalNumber::beforeFirst())
63 , m_parserInserted(parserInserted) 64 , m_parserInserted(parserInserted)
64 , m_isExternalScript(false) 65 , m_isExternalScript(false)
65 , m_alreadyStarted(alreadyStarted) 66 , m_alreadyStarted(alreadyStarted)
66 , m_haveFiredLoad(false) 67 , m_haveFiredLoad(false)
67 , m_willBeParserExecuted(false) 68 , m_willBeParserExecuted(false)
68 , m_readyToBeParserExecuted(false) 69 , m_readyToBeParserExecuted(false)
69 , m_willExecuteInOrder(false)
70 , m_willExecuteWhenDocumentFinishedParsing(false) 70 , m_willExecuteWhenDocumentFinishedParsing(false)
71 , m_forceAsync(!parserInserted) 71 , m_forceAsync(!parserInserted)
72 , m_createdDuringDocumentWrite(createdDuringDocumentWrite) 72 , m_createdDuringDocumentWrite(createdDuringDocumentWrite)
73 { 73 {
74 DCHECK(m_element); 74 DCHECK(m_element);
75 if (parserInserted && element->document().scriptableDocumentParser() && !ele ment->document().isInDocumentWrite()) 75 if (parserInserted && element->document().scriptableDocumentParser() && !ele ment->document().isInDocumentWrite())
76 m_startLineNumber = element->document().scriptableDocumentParser()->line Number(); 76 m_startLineNumber = element->document().scriptableDocumentParser()->line Number();
77 } 77 }
78 78
79 ScriptLoader::~ScriptLoader() 79 ScriptLoader::~ScriptLoader()
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) { 247 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) {
248 m_willExecuteWhenDocumentFinishedParsing = true; 248 m_willExecuteWhenDocumentFinishedParsing = true;
249 m_willBeParserExecuted = true; 249 m_willBeParserExecuted = true;
250 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) { 250 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) {
251 m_willBeParserExecuted = true; 251 m_willBeParserExecuted = true;
252 } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocu ment.isScriptExecutionReady()) { 252 } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocu ment.isScriptExecutionReady()) {
253 m_willBeParserExecuted = true; 253 m_willBeParserExecuted = true;
254 m_readyToBeParserExecuted = true; 254 m_readyToBeParserExecuted = true;
255 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) { 255 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) {
256 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 256 m_pendingScript = PendingScript::create(m_element, m_resource.get());
257 m_willExecuteInOrder = true; 257 m_asyncExecType = ScriptRunner::IN_ORDER_EXECUTION;
258 contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRun ner::IN_ORDER_EXECUTION); 258 contextDocument->scriptRunner()->queueScriptForExecution(this, m_asyncEx ecType.value());
259 // Note that watchForLoad can immediately call notifyFinished. 259 // Note that watchForLoad can immediately call notifyFinished.
260 m_pendingScript->watchForLoad(this); 260 m_pendingScript->watchForLoad(this);
261 } else if (client->hasSourceAttribute()) { 261 } else if (client->hasSourceAttribute()) {
262 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 262 m_pendingScript = PendingScript::create(m_element, m_resource.get());
263 m_asyncExecType = ScriptRunner::ASYNC_EXECUTION;
263 LocalFrame* frame = m_element->document().frame(); 264 LocalFrame* frame = m_element->document().frame();
264 if (frame) { 265 if (frame) {
265 ScriptState* scriptState = ScriptState::forMainWorld(frame); 266 ScriptState* scriptState = ScriptState::forMainWorld(frame);
266 if (scriptState) 267 if (scriptState)
267 ScriptStreamer::startStreaming(m_pendingScript.get(), ScriptStre amer::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTas kRunner()); 268 ScriptStreamer::startStreaming(m_pendingScript.get(), ScriptStre amer::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTas kRunner());
268 } 269 }
269 contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRun ner::ASYNC_EXECUTION); 270 contextDocument->scriptRunner()->queueScriptForExecution(this, m_asyncEx ecType.value());
270 // Note that watchForLoad can immediately call notifyFinished. 271 // Note that watchForLoad can immediately call notifyFinished.
271 m_pendingScript->watchForLoad(this); 272 m_pendingScript->watchForLoad(this);
272 } else { 273 } else {
273 // Reset line numbering for nested writes. 274 // Reset line numbering for nested writes.
274 TextPosition position = elementDocument.isInDocumentWrite() ? TextPositi on() : scriptStartPosition; 275 TextPosition position = elementDocument.isInDocumentWrite() ? TextPositi on() : scriptStartPosition;
275 KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInsert ed) ? elementDocument.url() : KURL(); 276 KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInsert ed) ? elementDocument.url() : KURL();
276 if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position ))) { 277 if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position ))) {
277 dispatchErrorEvent(); 278 dispatchErrorEvent();
278 return false; 279 return false;
279 } 280 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url()); 350 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url());
350 if (expectedJs) { 351 if (expectedJs) {
351 return; 352 return;
352 } 353 }
353 UseCounter::Feature feature = sameOrigin ? (text ? UseCounter::SameOriginTex tScript : application ? UseCounter::SameOriginApplicationScript : UseCounter::Sa meOriginOtherScript) : (text ? UseCounter::CrossOriginTextScript : application ? UseCounter::CrossOriginApplicationScript : UseCounter::CrossOriginOtherScript); 354 UseCounter::Feature feature = sameOrigin ? (text ? UseCounter::SameOriginTex tScript : application ? UseCounter::SameOriginApplicationScript : UseCounter::Sa meOriginOtherScript) : (text ? UseCounter::CrossOriginTextScript : application ? UseCounter::CrossOriginApplicationScript : UseCounter::CrossOriginOtherScript);
354 UseCounter::count(frame, feature); 355 UseCounter::count(frame, feature);
355 } 356 }
356 357
357 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) 358 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
358 { 359 {
360 double scriptExecStartTime = monotonicallyIncreasingTime();
361 bool result = doExecuteScript(sourceCode);
362
363 // NOTE: we do not check m_willBeParserExecuted here, since
364 // m_willBeParserExecuted is false for inline scripts, and we want to
365 // include inline script execution time as part of parser blocked script
366 // execution time.
367 if (!m_asyncExecType)
368 DocumentParserTiming::from(m_element->document()).recordParserBlockedOnS criptExecutionDuration(monotonicallyIncreasingTime() - scriptExecStartTime, wasC reatedDuringDocumentWrite());
369 return result;
370 }
371
372 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode)
373 {
359 DCHECK(m_alreadyStarted); 374 DCHECK(m_alreadyStarted);
360 375
361 if (sourceCode.isEmpty()) 376 if (sourceCode.isEmpty())
362 return true; 377 return true;
363 378
364 Document* elementDocument = &(m_element->document()); 379 Document* elementDocument = &(m_element->document());
365 Document* contextDocument = elementDocument->contextDocument(); 380 Document* contextDocument = elementDocument->contextDocument();
366 if (!contextDocument) 381 if (!contextDocument)
367 return true; 382 return true;
368 383
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 DCHECK(contextDocument->currentScript() == m_element); 447 DCHECK(contextDocument->currentScript() == m_element);
433 contextDocument->popCurrentScript(); 448 contextDocument->popCurrentScript();
434 } 449 }
435 450
436 return true; 451 return true;
437 } 452 }
438 453
439 void ScriptLoader::execute() 454 void ScriptLoader::execute()
440 { 455 {
441 DCHECK(!m_willBeParserExecuted); 456 DCHECK(!m_willBeParserExecuted);
457 DCHECK(m_asyncExecType);
442 DCHECK(m_pendingScript->resource()); 458 DCHECK(m_pendingScript->resource());
443 bool errorOccurred = false; 459 bool errorOccurred = false;
444 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); 460 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred);
445 Element* element = m_pendingScript->releaseElementAndClear(); 461 Element* element = m_pendingScript->releaseElementAndClear();
446 ALLOW_UNUSED_LOCAL(element); 462 ALLOW_UNUSED_LOCAL(element);
447 if (errorOccurred) { 463 if (errorOccurred) {
448 dispatchErrorEvent(); 464 dispatchErrorEvent();
449 } else if (!m_resource->wasCanceled()) { 465 } else if (!m_resource->wasCanceled()) {
450 if (executeScript(source)) 466 if (executeScript(source))
451 dispatchLoadEvent(); 467 dispatchLoadEvent();
452 else 468 else
453 dispatchErrorEvent(); 469 dispatchErrorEvent();
454 } 470 }
455 m_resource = nullptr; 471 m_resource = nullptr;
456 } 472 }
457 473
458 void ScriptLoader::notifyFinished(Resource* resource) 474 void ScriptLoader::notifyFinished(Resource* resource)
459 { 475 {
460 DCHECK(!m_willBeParserExecuted); 476 DCHECK(!m_willBeParserExecuted);
477 DCHECK(m_asyncExecType);
461 478
462 Document* contextDocument = m_element->document().contextDocument(); 479 Document* contextDocument = m_element->document().contextDocument();
463 if (!contextDocument) { 480 if (!contextDocument) {
464 detach(); 481 detach();
465 return; 482 return;
466 } 483 }
467 484
468 ASSERT_UNUSED(resource, resource == m_resource); 485 ASSERT_UNUSED(resource, resource == m_resource);
469 486
470 ScriptRunner::ExecutionType runOrder = m_willExecuteInOrder ? ScriptRunner:: IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION;
471 if (m_resource->errorOccurred()) { 487 if (m_resource->errorOccurred()) {
472 contextDocument->scriptRunner()->notifyScriptLoadError(this, runOrder); 488 contextDocument->scriptRunner()->notifyScriptLoadError(this, m_asyncExec Type.value());
473 detach(); 489 detach();
474 dispatchErrorEvent(); 490 dispatchErrorEvent();
475 return; 491 return;
476 } 492 }
477 contextDocument->scriptRunner()->notifyScriptReady(this, runOrder); 493 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType.val ue());
478 m_pendingScript->stopWatchingForLoad(); 494 m_pendingScript->stopWatchingForLoad();
479 } 495 }
480 496
481 bool ScriptLoader::ignoresLoadRequest() const 497 bool ScriptLoader::ignoresLoadRequest() const
482 { 498 {
483 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected(); 499 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected();
484 } 500 }
485 501
486 bool ScriptLoader::isScriptForEventSupported() const 502 bool ScriptLoader::isScriptForEventSupported() const
487 { 503 {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 if (isHTMLScriptLoader(element)) 535 if (isHTMLScriptLoader(element))
520 return toHTMLScriptElement(element)->loader(); 536 return toHTMLScriptElement(element)->loader();
521 537
522 if (isSVGScriptLoader(element)) 538 if (isSVGScriptLoader(element))
523 return toSVGScriptElement(element)->loader(); 539 return toSVGScriptElement(element)->loader();
524 540
525 return 0; 541 return 0;
526 } 542 }
527 543
528 } // namespace blink 544 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698