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

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: fix test 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::NoExecType)
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::InOrderExecution;
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::AsyncExecution;
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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url()); 351 bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_re source->url());
350 if (expectedJs) { 352 if (expectedJs) {
351 return; 353 return;
352 } 354 }
353 UseCounter::Feature feature = sameOrigin ? (text ? UseCounter::SameOriginTex tScript : application ? UseCounter::SameOriginApplicationScript : UseCounter::Sa meOriginOtherScript) : (text ? UseCounter::CrossOriginTextScript : application ? UseCounter::CrossOriginApplicationScript : UseCounter::CrossOriginOtherScript); 355 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); 356 UseCounter::count(frame, feature);
355 } 357 }
356 358
357 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) 359 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
358 { 360 {
361 double scriptExecStartTime = monotonicallyIncreasingTime();
362 bool result = doExecuteScript(sourceCode);
363
364 // NOTE: we do not check m_willBeParserExecuted here, since
365 // m_willBeParserExecuted is false for inline scripts, and we want to
366 // include inline script execution time as part of parser blocked script
367 // execution time.
368 if (m_asyncExecType == ScriptRunner::NoExecType)
369 DocumentParserTiming::from(m_element->document()).recordParserBlockedOnS criptExecutionDuration(monotonicallyIncreasingTime() - scriptExecStartTime, wasC reatedDuringDocumentWrite());
370 return result;
371 }
372
373 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode)
374 {
359 DCHECK(m_alreadyStarted); 375 DCHECK(m_alreadyStarted);
360 376
361 if (sourceCode.isEmpty()) 377 if (sourceCode.isEmpty())
362 return true; 378 return true;
363 379
364 Document* elementDocument = &(m_element->document()); 380 Document* elementDocument = &(m_element->document());
365 Document* contextDocument = elementDocument->contextDocument(); 381 Document* contextDocument = elementDocument->contextDocument();
366 if (!contextDocument) 382 if (!contextDocument)
367 return true; 383 return true;
368 384
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 DCHECK(contextDocument->currentScript() == m_element); 448 DCHECK(contextDocument->currentScript() == m_element);
433 contextDocument->popCurrentScript(); 449 contextDocument->popCurrentScript();
434 } 450 }
435 451
436 return true; 452 return true;
437 } 453 }
438 454
439 void ScriptLoader::execute() 455 void ScriptLoader::execute()
440 { 456 {
441 DCHECK(!m_willBeParserExecuted); 457 DCHECK(!m_willBeParserExecuted);
458 DCHECK(m_asyncExecType != ScriptRunner::NoExecType);
442 DCHECK(m_pendingScript->resource()); 459 DCHECK(m_pendingScript->resource());
443 bool errorOccurred = false; 460 bool errorOccurred = false;
444 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); 461 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred);
445 Element* element = m_pendingScript->releaseElementAndClear(); 462 Element* element = m_pendingScript->releaseElementAndClear();
446 ALLOW_UNUSED_LOCAL(element); 463 ALLOW_UNUSED_LOCAL(element);
447 if (errorOccurred) { 464 if (errorOccurred) {
448 dispatchErrorEvent(); 465 dispatchErrorEvent();
449 } else if (!m_resource->wasCanceled()) { 466 } else if (!m_resource->wasCanceled()) {
450 if (executeScript(source)) 467 if (executeScript(source))
451 dispatchLoadEvent(); 468 dispatchLoadEvent();
452 else 469 else
453 dispatchErrorEvent(); 470 dispatchErrorEvent();
454 } 471 }
455 m_resource = nullptr; 472 m_resource = nullptr;
456 } 473 }
457 474
458 void ScriptLoader::notifyFinished(Resource* resource) 475 void ScriptLoader::notifyFinished(Resource* resource)
459 { 476 {
460 DCHECK(!m_willBeParserExecuted); 477 DCHECK(!m_willBeParserExecuted);
478 DCHECK(m_asyncExecType != ScriptRunner::NoExecType);
461 479
462 Document* contextDocument = m_element->document().contextDocument(); 480 Document* contextDocument = m_element->document().contextDocument();
463 if (!contextDocument) { 481 if (!contextDocument) {
464 detach(); 482 detach();
465 return; 483 return;
466 } 484 }
467 485
468 ASSERT_UNUSED(resource, resource == m_resource); 486 ASSERT_UNUSED(resource, resource == m_resource);
469 487
470 ScriptRunner::ExecutionType runOrder = m_willExecuteInOrder ? ScriptRunner:: IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION;
471 if (m_resource->errorOccurred()) { 488 if (m_resource->errorOccurred()) {
472 contextDocument->scriptRunner()->notifyScriptLoadError(this, runOrder); 489 contextDocument->scriptRunner()->notifyScriptLoadError(this, m_asyncExec Type);
473 detach(); 490 detach();
474 dispatchErrorEvent(); 491 dispatchErrorEvent();
475 return; 492 return;
476 } 493 }
477 contextDocument->scriptRunner()->notifyScriptReady(this, runOrder); 494 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType);
478 m_pendingScript->stopWatchingForLoad(); 495 m_pendingScript->stopWatchingForLoad();
479 } 496 }
480 497
481 bool ScriptLoader::ignoresLoadRequest() const 498 bool ScriptLoader::ignoresLoadRequest() const
482 { 499 {
483 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected(); 500 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->isConnected();
484 } 501 }
485 502
486 bool ScriptLoader::isScriptForEventSupported() const 503 bool ScriptLoader::isScriptForEventSupported() const
487 { 504 {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 if (isHTMLScriptLoader(element)) 536 if (isHTMLScriptLoader(element))
520 return toHTMLScriptElement(element)->loader(); 537 return toHTMLScriptElement(element)->loader();
521 538
522 if (isSVGScriptLoader(element)) 539 if (isSVGScriptLoader(element))
523 return toSVGScriptElement(element)->loader(); 540 return toSVGScriptElement(element)->loader();
524 541
525 return 0; 542 return 0;
526 } 543 }
527 544
528 } // namespace blink 545 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698