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

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: address comments 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 , m_asyncExecType(ScriptRunner::None)
73 { 74 {
74 DCHECK(m_element); 75 DCHECK(m_element);
75 if (parserInserted && element->document().scriptableDocumentParser() && !ele ment->document().isInDocumentWrite()) 76 if (parserInserted && element->document().scriptableDocumentParser() && !ele ment->document().isInDocumentWrite())
76 m_startLineNumber = element->document().scriptableDocumentParser()->line Number(); 77 m_startLineNumber = element->document().scriptableDocumentParser()->line Number();
77 } 78 }
78 79
79 ScriptLoader::~ScriptLoader() 80 ScriptLoader::~ScriptLoader()
80 { 81 {
81 } 82 }
82 83
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) { 248 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) {
248 m_willExecuteWhenDocumentFinishedParsing = true; 249 m_willExecuteWhenDocumentFinishedParsing = true;
249 m_willBeParserExecuted = true; 250 m_willBeParserExecuted = true;
250 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) { 251 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) {
251 m_willBeParserExecuted = true; 252 m_willBeParserExecuted = true;
252 } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocu ment.isScriptExecutionReady()) { 253 } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocu ment.isScriptExecutionReady()) {
253 m_willBeParserExecuted = true; 254 m_willBeParserExecuted = true;
254 m_readyToBeParserExecuted = true; 255 m_readyToBeParserExecuted = true;
255 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) { 256 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) {
256 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 257 m_pendingScript = PendingScript::create(m_element, m_resource.get());
257 m_willExecuteInOrder = true; 258 m_asyncExecType = ScriptRunner::InOrder;
258 contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRun ner::IN_ORDER_EXECUTION); 259 contextDocument->scriptRunner()->queueScriptForExecution(this, m_asyncEx ecType);
259 // Note that watchForLoad can immediately call notifyFinished. 260 // Note that watchForLoad can immediately call notifyFinished.
260 m_pendingScript->watchForLoad(this); 261 m_pendingScript->watchForLoad(this);
261 } else if (client->hasSourceAttribute()) { 262 } else if (client->hasSourceAttribute()) {
262 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 263 m_pendingScript = PendingScript::create(m_element, m_resource.get());
264 m_asyncExecType = ScriptRunner::Async;
263 LocalFrame* frame = m_element->document().frame(); 265 LocalFrame* frame = m_element->document().frame();
264 if (frame) { 266 if (frame) {
265 ScriptState* scriptState = ScriptState::forMainWorld(frame); 267 ScriptState* scriptState = ScriptState::forMainWorld(frame);
266 if (scriptState) 268 if (scriptState)
267 ScriptStreamer::startStreaming(m_pendingScript.get(), ScriptStre amer::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTas kRunner()); 269 ScriptStreamer::startStreaming(m_pendingScript.get(), ScriptStre amer::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTas kRunner());
268 } 270 }
269 contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRun ner::ASYNC_EXECUTION); 271 contextDocument->scriptRunner()->queueScriptForExecution(this, m_asyncEx ecType);
270 // Note that watchForLoad can immediately call notifyFinished. 272 // Note that watchForLoad can immediately call notifyFinished.
271 m_pendingScript->watchForLoad(this); 273 m_pendingScript->watchForLoad(this);
272 } else { 274 } else {
273 // Reset line numbering for nested writes. 275 // Reset line numbering for nested writes.
274 TextPosition position = elementDocument.isInDocumentWrite() ? TextPositi on() : scriptStartPosition; 276 TextPosition position = elementDocument.isInDocumentWrite() ? TextPositi on() : scriptStartPosition;
275 KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInsert ed) ? elementDocument.url() : KURL(); 277 KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInsert ed) ? elementDocument.url() : KURL();
276 if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position ))) { 278 if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position ))) {
277 dispatchErrorEvent(); 279 dispatchErrorEvent();
278 return false; 280 return false;
279 } 281 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url()); 352 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url());
351 if (expectedJs) { 353 if (expectedJs) {
352 return; 354 return;
353 } 355 }
354 UseCounter::Feature feature = sameOrigin ? (text ? UseCounter::SameOriginTex tScript : application ? UseCounter::SameOriginApplicationScript : UseCounter::Sa meOriginOtherScript) : (text ? UseCounter::CrossOriginTextScript : application ? UseCounter::CrossOriginApplicationScript : UseCounter::CrossOriginOtherScript); 356 UseCounter::Feature feature = sameOrigin ? (text ? UseCounter::SameOriginTex tScript : application ? UseCounter::SameOriginApplicationScript : UseCounter::Sa meOriginOtherScript) : (text ? UseCounter::CrossOriginTextScript : application ? UseCounter::CrossOriginApplicationScript : UseCounter::CrossOriginOtherScript);
355 UseCounter::count(frame, feature); 357 UseCounter::count(frame, feature);
356 } 358 }
357 359
358 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) 360 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
359 { 361 {
362 double scriptExecStartTime = monotonicallyIncreasingTime();
363 bool result = doExecuteScript(sourceCode);
364
365 // NOTE: we do not check m_willBeParserExecuted here, since
366 // m_willBeParserExecuted is false for inline scripts, and we want to
367 // include inline script execution time as part of parser blocked script
368 // execution time.
369 if (m_asyncExecType == ScriptRunner::None)
370 DocumentParserTiming::from(m_element->document()).recordParserBlockedOnS criptExecutionDuration(monotonicallyIncreasingTime() - scriptExecStartTime, wasC reatedDuringDocumentWrite());
371 return result;
372 }
373
374 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode)
375 {
360 DCHECK(m_alreadyStarted); 376 DCHECK(m_alreadyStarted);
361 377
362 if (sourceCode.isEmpty()) 378 if (sourceCode.isEmpty())
363 return true; 379 return true;
364 380
365 Document* elementDocument = &(m_element->document()); 381 Document* elementDocument = &(m_element->document());
366 Document* contextDocument = elementDocument->contextDocument(); 382 Document* contextDocument = elementDocument->contextDocument();
367 if (!contextDocument) 383 if (!contextDocument)
368 return true; 384 return true;
369 385
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 DCHECK(contextDocument->currentScript() == m_element); 457 DCHECK(contextDocument->currentScript() == m_element);
442 contextDocument->popCurrentScript(); 458 contextDocument->popCurrentScript();
443 } 459 }
444 460
445 return true; 461 return true;
446 } 462 }
447 463
448 void ScriptLoader::execute() 464 void ScriptLoader::execute()
449 { 465 {
450 DCHECK(!m_willBeParserExecuted); 466 DCHECK(!m_willBeParserExecuted);
467 DCHECK(m_asyncExecType != ScriptRunner::None);
451 DCHECK(m_pendingScript->resource()); 468 DCHECK(m_pendingScript->resource());
452 bool errorOccurred = false; 469 bool errorOccurred = false;
453 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); 470 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred);
454 Element* element = m_pendingScript->releaseElementAndClear(); 471 Element* element = m_pendingScript->releaseElementAndClear();
455 ALLOW_UNUSED_LOCAL(element); 472 ALLOW_UNUSED_LOCAL(element);
456 if (errorOccurred) { 473 if (errorOccurred) {
457 dispatchErrorEvent(); 474 dispatchErrorEvent();
458 } else if (!m_resource->wasCanceled()) { 475 } else if (!m_resource->wasCanceled()) {
459 if (executeScript(source)) 476 if (executeScript(source))
460 dispatchLoadEvent(); 477 dispatchLoadEvent();
461 else 478 else
462 dispatchErrorEvent(); 479 dispatchErrorEvent();
463 } 480 }
464 m_resource = nullptr; 481 m_resource = nullptr;
465 } 482 }
466 483
467 void ScriptLoader::notifyFinished(Resource* resource) 484 void ScriptLoader::notifyFinished(Resource* resource)
468 { 485 {
469 DCHECK(!m_willBeParserExecuted); 486 DCHECK(!m_willBeParserExecuted);
487 DCHECK(m_asyncExecType != ScriptRunner::None);
470 488
471 Document* contextDocument = m_element->document().contextDocument(); 489 Document* contextDocument = m_element->document().contextDocument();
472 if (!contextDocument) { 490 if (!contextDocument) {
473 detach(); 491 detach();
474 return; 492 return;
475 } 493 }
476 494
477 ASSERT_UNUSED(resource, resource == m_resource); 495 ASSERT_UNUSED(resource, resource == m_resource);
478 496
479 ScriptRunner::ExecutionType runOrder = m_willExecuteInOrder ? ScriptRunner:: IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION;
480 if (m_resource->errorOccurred()) { 497 if (m_resource->errorOccurred()) {
481 contextDocument->scriptRunner()->notifyScriptLoadError(this, runOrder); 498 contextDocument->scriptRunner()->notifyScriptLoadError(this, m_asyncExec Type);
482 detach(); 499 detach();
483 dispatchErrorEvent(); 500 dispatchErrorEvent();
484 return; 501 return;
485 } 502 }
486 contextDocument->scriptRunner()->notifyScriptReady(this, runOrder); 503 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType);
487 m_pendingScript->stopWatchingForLoad(); 504 m_pendingScript->stopWatchingForLoad();
488 } 505 }
489 506
490 bool ScriptLoader::ignoresLoadRequest() const 507 bool ScriptLoader::ignoresLoadRequest() const
491 { 508 {
492 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected(); 509 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected();
493 } 510 }
494 511
495 bool ScriptLoader::isScriptForEventSupported() const 512 bool ScriptLoader::isScriptForEventSupported() const
496 { 513 {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 if (isHTMLScriptLoader(element)) 545 if (isHTMLScriptLoader(element))
529 return toHTMLScriptElement(element)->loader(); 546 return toHTMLScriptElement(element)->loader();
530 547
531 if (isSVGScriptLoader(element)) 548 if (isSVGScriptLoader(element))
532 return toSVGScriptElement(element)->loader(); 549 return toSVGScriptElement(element)->loader();
533 550
534 return 0; 551 return 0;
535 } 552 }
536 553
537 } // namespace blink 554 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/ScriptLoader.h ('k') | third_party/WebKit/Source/core/dom/ScriptRunner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698