Changeset 205218 in webkit
- Timestamp:
- Aug 30, 2016 7:37:12 PM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 11 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r205214 r205218 1 2016-08-30 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 Make PendingScript as ref-counted 4 https://bugs.webkit.org/show_bug.cgi?id=161350 5 6 Reviewed by Ryosuke Niwa. 7 8 Currently, while PendingScript is copyable, PendingScript is also CachedResourceClient. 9 So when copying this, the client registration is done in PendingScript's operator= etc. 10 However, this copying functionality is not effectively used. 11 In this patch, we change this PendingScript to ref-counted class and make it noncopyable. 12 This change makes things simple (dropping this copying functionality), and drops unnecessary 13 addClient / removeClient calls. And we also simplify PendingScript class. Since we can offer 14 all the members at the construction time, we do not need any setters like setCachedScript, 15 setElement etc. This prevents us from accidentally generating the half-baked pending script. 16 17 Furthermore, by changing PendingScript noncopyable & ref-counted, we easily make it 18 observable. In this patch, we add PendingScriptClient to receive the notification from 19 PendingScript. Previously, we directly used CachedScript in PendingScript to receive the 20 notification. When introducing ScriptModuleGraph and making this PendingScript the container 21 of the both CachedScript and ScriptModuleGraph, hiding the raw CachedScript operations is 22 useful. 23 24 No behavior changes. 25 26 * WebCore.xcodeproj/project.pbxproj: 27 * dom/PendingScript.cpp: 28 (WebCore::PendingScript::create): These factory functions take all the information needed 29 to construct the PendingScript. So the setters of PendingScript are dropped. This is better 30 since we now do not expose any half-baked pending script accidentally. 31 (WebCore::PendingScript::PendingScript): 32 (WebCore::PendingScript::~PendingScript): 33 (WebCore::PendingScript::notifyClientFinished): 34 (WebCore::PendingScript::notifyFinished): 35 (WebCore::PendingScript::isLoaded): When introducing ScriptModuleGraph, this will query to 36 either CachedScript or ScriptModuleGraph. PendingScript will become the container for the 37 both types. 38 (WebCore::PendingScript::setClient): 39 (WebCore::PendingScript::clearClient): PendingScript is now observable by PendingScriptClient. 40 This avoids touching CachedScript in PendingScript directly. That is good when we introduce 41 ScriptModuleGraph and make PendingScript the container of the both CachedScript and ScriptModuleGraph. 42 (WebCore::PendingScript::releaseElementAndClear): Deleted. Previously, PendingScript is not ref-counted. 43 So when we would like to say "this pending script is empty", we used the pending script with 44 `m_element = nullptr`. This releaseElementAndClear cleared this m_element and made the pending 45 script empty. Now, we use RefPtr<PendingScript> and empty one is just represented by the nullptr. 46 This function is no longer necessary. Dropped. 47 (WebCore::PendingScript::setCachedScript): Deleted. The fields are set in the constructor. 48 So this setter is no longer necessary. Dropped. 49 * dom/PendingScript.h: 50 * dom/PendingScriptClient.h: Copied from Source/WebCore/html/parser/HTMLScriptRunnerHost.h. 51 (WebCore::PendingScriptClient::~PendingScriptClient): 52 * dom/ScriptRunner.cpp: 53 (WebCore::ScriptRunner::queueScriptForExecution): 54 (WebCore::ScriptRunner::notifyScriptReady): 55 (WebCore::ScriptRunner::timerFired): We use `std::exchange` to retrieve the RefPtr<PendingScript> 56 and make the original vector element nullptr. Without this, all the PendingScript is held until 57 the iteration finishes. We keep the original semantics here that the pending script can be 58 released per iteration. 59 * dom/ScriptRunner.h: 60 * html/parser/HTMLDocumentParser.cpp: 61 (WebCore::HTMLDocumentParser::watchForLoad): 62 (WebCore::HTMLDocumentParser::stopWatchingForLoad): Use PendingScript instead of touching 63 CachedScript directly. 64 (WebCore::HTMLDocumentParser::notifyFinished): 65 * html/parser/HTMLDocumentParser.h: 66 * html/parser/HTMLScriptRunner.cpp: 67 (WebCore::HTMLScriptRunner::~HTMLScriptRunner): 68 (WebCore::HTMLScriptRunner::sourceFromPendingScript): 69 (WebCore::HTMLScriptRunner::isPendingScriptReady): 70 (WebCore::HTMLScriptRunner::executeParsingBlockingScript): 71 (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent): As the previous comment describes, 72 we used releaseElementAndClear to make the current pending script empty. Instead of doing so, we now 73 explicitly clear executeParsingBlockingScript (by assigning nullptr to m_parserBlockingScript). 74 (WebCore::HTMLScriptRunner::watchForLoad): 75 (WebCore::HTMLScriptRunner::stopWatchingForLoad): Previously, we used CachedScript::addClient directly 76 in the m_host.watchForLoad. This means that we did not have a quick way to query whether the pending 77 script is watched. In the old implementation, we have the `m_watchingForLoad : bool` flag in PendingScript 78 to hold the watching status for the given pending script. This `pendingScript.setWatchingForLoad(true)` 79 just made this flag `true`. But now, we do not use CachedScript::addClient directly. Instead, we have 80 the PendingScriptClient and PendingScript::{setClient,clearClient}. We can know whether this pending 81 script is watched by checking `m_client != nullptr`. This makes `m_watchingForLoad` unnecessary. 82 So this patch drops `m_watchingForLoad` and `pendingScript.setWatchingForLoad(true)` call. 83 (WebCore::HTMLScriptRunner::hasParserBlockingScript): 84 (WebCore::HTMLScriptRunner::executeParsingBlockingScripts): We clear the m_parserBlockingScript here 85 instead of the middle of the executePendingScriptAndDispatchEvent. 86 (WebCore::HTMLScriptRunner::executeScriptsWaitingForLoad): 87 (WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing): 88 (WebCore::requestPendingScript): 89 (WebCore::HTMLScriptRunner::requestParsingBlockingScript): Setting m_parsingBlockingScript is now done 90 in this caller side. 91 (WebCore::HTMLScriptRunner::requestDeferredScript): 92 (WebCore::HTMLScriptRunner::runScript): 93 (WebCore::HTMLScriptRunner::requestPendingScript): Instead of configuring the passed PendingScript&, 94 we return the pending script and the caller sets it to m_parserBlockingScript or holds it. And we now 95 change this function to static location one and drop the member function. Previously, we always make 96 PendingScript& valid by always calling `setElement(...)`. I think this is the bug since we accidentally 97 exposed the half-baked pending script. But this bug is not shown since `!cachedScript` path is dead code! 98 This requestPendingScript is called from two places, requestDeferredScript and requestParsingBlockingScript. 99 And these functions are called if the script has `willBeParserExecuted` flag. In the case of the script 100 tag having "src" attribute, this flag is only set if `cachedScript` is correctly instantiated. So when 101 these functions are called, we can ensure that `cachedScript` is correctly instantiated for the given script. 102 In the case of the script tag not having "src" attribute, these functions are won't be called. This is 103 because if such a script tag has `willBeParserExecuted` flag, it also has `m_readyToBeParserExecuted` 104 and it does not have `m_willExecuteWhenDocumentFinishedParsing` flag, and in that case the both 105 functions are never called. So we drop that path and insert the assertion to ensure the above conditions. 106 * html/parser/HTMLScriptRunner.h: 107 * html/parser/HTMLScriptRunnerHost.h: 108 1 109 2016-08-30 Ricky Mondello <rmondello@apple.com> 2 110 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r205212 r205218 6092 6092 E38838981BAD145F00D62EE3 /* JSModuleLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38838941BAD145F00D62EE3 /* JSModuleLoader.cpp */; }; 6093 6093 E38838991BAD145F00D62EE3 /* JSModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E38838951BAD145F00D62EE3 /* JSModuleLoader.h */; }; 6094 E3FA38641D71812D00AA5950 /* PendingScriptClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E3FA38611D716E7600AA5950 /* PendingScriptClient.h */; }; 6094 6095 E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6095 6096 E401E0A41C3C0B8300F34D10 /* StyleChange.h in Headers */ = {isa = PBXBuildFile; fileRef = E401E0A31C3C0B8300F34D10 /* StyleChange.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 13658 13659 E38838941BAD145F00D62EE3 /* JSModuleLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleLoader.cpp; sourceTree = "<group>"; }; 13659 13660 E38838951BAD145F00D62EE3 /* JSModuleLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleLoader.h; sourceTree = "<group>"; }; 13661 E3FA38611D716E7600AA5950 /* PendingScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScriptClient.h; sourceTree = "<group>"; }; 13660 13662 E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; }; 13661 13663 E401E0A31C3C0B8300F34D10 /* StyleChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleChange.h; sourceTree = "<group>"; }; … … 23081 23083 8A7CC96F12076F8A001D4588 /* PendingScript.cpp */, 23082 23084 8A7CC96A12076D73001D4588 /* PendingScript.h */, 23085 E3FA38611D716E7600AA5950 /* PendingScriptClient.h */, 23083 23086 41BF700D0FE86F61005E8DEC /* PlatformMessagePortChannel.cpp */, 23084 23087 41BF700E0FE86F61005E8DEC /* PlatformMessagePortChannel.h */, … … 27057 27060 BC772C470C4EB2C60083285F /* XMLHttpRequest.h in Headers */, 27058 27061 83D35AEC1C7187FA00F70D5A /* XMLHttpRequestEventTarget.h in Headers */, 27062 E3FA38641D71812D00AA5950 /* PendingScriptClient.h in Headers */, 27059 27063 F9F0ED7A0DB50CA200D16DB9 /* XMLHttpRequestProgressEvent.h in Headers */, 27060 27064 A136A00D1134DBD200CC8D50 /* XMLHttpRequestProgressEventThrottle.h in Headers */, -
trunk/Source/WebCore/dom/PendingScript.cpp
r195243 r205218 29 29 #include "CachedScript.h" 30 30 #include "Element.h" 31 #include "PendingScriptClient.h" 31 32 32 33 namespace WebCore { 34 35 Ref<PendingScript> PendingScript::create(Element& element, CachedScript& cachedScript) 36 { 37 Ref<PendingScript> pendingScript = adoptRef(*new PendingScript(element, cachedScript)); 38 cachedScript.addClient(&pendingScript.get()); 39 return pendingScript; 40 } 41 42 Ref<PendingScript> PendingScript::create(Element& element, TextPosition scriptStartPosition) 43 { 44 return adoptRef(*new PendingScript(element, scriptStartPosition)); 45 } 46 47 PendingScript::PendingScript(Element& element, TextPosition startingPosition) 48 : m_element(element) 49 , m_startingPosition(startingPosition) 50 { 51 } 52 53 PendingScript::PendingScript(Element& element, CachedScript& cachedScript) 54 : m_element(element) 55 , m_cachedScript(&cachedScript) 56 { 57 } 33 58 34 59 PendingScript::~PendingScript() … … 38 63 } 39 64 40 RefPtr<Element> PendingScript::releaseElementAndClear()41 {42 setCachedScript(nullptr);43 m_watchingForLoad = false;44 m_startingPosition = TextPosition::belowRangePosition();45 return WTFMove(m_element);46 }47 48 void PendingScript::setCachedScript(CachedScript* cachedScript)49 {50 if (m_cachedScript == cachedScript)51 return;52 if (m_cachedScript)53 m_cachedScript->removeClient(this);54 m_cachedScript = cachedScript;55 if (m_cachedScript)56 m_cachedScript->addClient(this);57 }58 59 65 CachedScript* PendingScript::cachedScript() const 60 66 { … … 62 68 } 63 69 70 void PendingScript::notifyClientFinished() 71 { 72 Ref<PendingScript> protectedThis(*this); 73 if (m_client) 74 m_client->notifyFinished(*this); 75 } 76 64 77 void PendingScript::notifyFinished(CachedResource*) 65 78 { 79 notifyClientFinished(); 80 } 81 82 bool PendingScript::isLoaded() const 83 { 84 return m_cachedScript && m_cachedScript->isLoaded(); 85 } 86 87 void PendingScript::setClient(PendingScriptClient* client) 88 { 89 ASSERT(!m_client); 90 m_client = client; 91 if (isLoaded()) 92 notifyClientFinished(); 93 } 94 95 void PendingScript::clearClient() 96 { 97 ASSERT(m_client); 98 m_client = nullptr; 66 99 } 67 100 -
trunk/Source/WebCore/dom/PendingScript.h
r197563 r205218 24 24 */ 25 25 26 #ifndef PendingScript_h 27 #define PendingScript_h 26 #pragma once 28 27 29 28 #include "CachedResourceClient.h" 30 29 #include "CachedResourceHandle.h" 30 #include <wtf/Ref.h> 31 #include <wtf/RefCounted.h> 31 32 #include <wtf/text/TextPosition.h> 32 #include <wtf/RefPtr.h>33 33 34 34 namespace WebCore { … … 36 36 class CachedScript; 37 37 class Element; 38 class PendingScriptClient; 38 39 39 40 // A container for an external script which may be loaded and executed. … … 42 43 // from purging its data buffer. This class holds a dummy client open for its 43 44 // lifetime in order to guarantee that the data buffer will not be purged. 44 class PendingScript final : public CachedResourceClient {45 class PendingScript final : public RefCounted<PendingScript>, public CachedResourceClient { 45 46 public: 46 PendingScript() 47 : m_watchingForLoad(false) 48 , m_startingPosition(TextPosition::belowRangePosition()) 49 { 50 } 51 52 PendingScript(Element* element, CachedScript* cachedScript) 53 : m_watchingForLoad(false) 54 , m_element(element) 55 { 56 setCachedScript(cachedScript); 57 } 58 59 PendingScript(const PendingScript& other) 60 : CachedResourceClient(other) 61 , m_watchingForLoad(other.m_watchingForLoad) 62 , m_element(other.m_element) 63 , m_startingPosition(other.m_startingPosition) 64 { 65 setCachedScript(other.cachedScript()); 66 } 47 static Ref<PendingScript> create(Element&, CachedScript&); 48 static Ref<PendingScript> create(Element&, TextPosition scriptStartPosition); 67 49 68 50 virtual ~PendingScript(); 69 70 PendingScript& operator=(const PendingScript& other)71 {72 if (this == &other)73 return *this;74 75 m_watchingForLoad = other.m_watchingForLoad;76 m_element = other.m_element;77 m_startingPosition = other.m_startingPosition;78 setCachedScript(other.cachedScript());79 80 return *this;81 }82 51 83 52 TextPosition startingPosition() const { return m_startingPosition; } 84 53 void setStartingPosition(const TextPosition& position) { m_startingPosition = position; } 85 54 86 bool watchingForLoad() const { return m_watchingForLoad; } 87 void setWatchingForLoad(bool b) { m_watchingForLoad = b; } 55 bool watchingForLoad() const { return needsLoading() && m_client; } 88 56 89 Element* element() const { return m_element.get(); } 90 void setElement(Element* element) { m_element = element; } 91 RefPtr<Element> releaseElementAndClear(); 57 Element& element() { return m_element.get(); } 58 const Element& element() const { return m_element.get(); } 92 59 93 60 CachedScript* cachedScript() const; 94 void setCachedScript(CachedScript*); 61 bool needsLoading() const { return cachedScript(); } 62 63 bool isLoaded() const; 95 64 96 65 void notifyFinished(CachedResource*) override; 97 66 67 void setClient(PendingScriptClient*); 68 void clearClient(); 69 98 70 private: 99 bool m_watchingForLoad; 100 RefPtr<Element> m_element; 71 PendingScript(Element&, CachedScript&); 72 PendingScript(Element&, TextPosition startingPosition); 73 74 void notifyClientFinished(); 75 76 Ref<Element> m_element; 101 77 TextPosition m_startingPosition; // Only used for inline script tags. 102 CachedResourceHandle<CachedScript> m_cachedScript; 78 CachedResourceHandle<CachedScript> m_cachedScript; 79 PendingScriptClient* m_client { nullptr }; 103 80 }; 104 81 105 82 } 106 107 #endif -
trunk/Source/WebCore/dom/PendingScriptClient.h
r205217 r205218 1 1 /* 2 * Copyright (C) 201 0 Google, Inc. All Rights Reserved.2 * Copyright (C) 2016 Apple, Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 #ifndef HTMLScriptRunnerHost_h 27 #define HTMLScriptRunnerHost_h 28 29 #include <wtf/Forward.h> 26 #pragma once 30 27 31 28 namespace WebCore { 32 29 33 class CachedResource; 34 class Element; 35 class HTMLInputStream; 36 class ScriptSourceCode; 30 class PendingScript; 37 31 38 class HTMLScriptRunnerHost {32 class PendingScriptClient { 39 33 public: 40 virtual ~ HTMLScriptRunnerHost() { }34 virtual ~PendingScriptClient() { } 41 35 42 // Implementors should call cachedResource->addClient() here or soon after. 43 virtual void watchForLoad(CachedResource*) = 0; 44 // Implementors must call cachedResource->removeClient() immediately. 45 virtual void stopWatchingForLoad(CachedResource*) = 0; 46 47 virtual HTMLInputStream& inputStream() = 0; 48 49 virtual bool hasPreloadScanner() const = 0; 50 virtual void appendCurrentInputStreamToPreloadScannerAndScan() = 0; 51 36 virtual void notifyFinished(PendingScript&) = 0; 52 37 }; 53 38 54 39 } 55 56 #endif -
trunk/Source/WebCore/dom/ScriptRunner.cpp
r193286 r205218 62 62 switch (executionType) { 63 63 case ASYNC_EXECUTION: 64 m_pendingAsyncScripts.add(scriptElement, PendingScript (&element, cachedScript.get()));64 m_pendingAsyncScripts.add(scriptElement, PendingScript::create(element, *cachedScript)); 65 65 break; 66 66 67 67 case IN_ORDER_EXECUTION: 68 m_scriptsToExecuteInOrder.append(PendingScript (&element, cachedScript.get()));68 m_scriptsToExecuteInOrder.append(PendingScript::create(element, *cachedScript)); 69 69 break; 70 70 } … … 87 87 case ASYNC_EXECUTION: 88 88 ASSERT(m_pendingAsyncScripts.contains(scriptElement)); 89 m_scriptsToExecuteSoon.append(m_pendingAsyncScripts.take(scriptElement) );89 m_scriptsToExecuteSoon.append(m_pendingAsyncScripts.take(scriptElement)->ptr()); 90 90 break; 91 91 … … 101 101 Ref<Document> protect(m_document); 102 102 103 Vector< PendingScript> scripts;103 Vector<RefPtr<PendingScript>> scripts; 104 104 scripts.swap(m_scriptsToExecuteSoon); 105 105 106 106 size_t numInOrderScriptsToExecute = 0; 107 for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute] .cachedScript()->isLoaded(); ++numInOrderScriptsToExecute)108 scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute] );107 for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute]->isLoaded(); ++numInOrderScriptsToExecute) 108 scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute].ptr()); 109 109 if (numInOrderScriptsToExecute) 110 110 m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute); 111 111 112 for (auto& script : scripts) { 113 CachedScript* cachedScript = script.cachedScript(); 114 RefPtr<Element> element = script.releaseElementAndClear(); 115 ASSERT(element); 112 for (auto& currentScript : scripts) { 113 auto script = WTFMove(currentScript); 114 ASSERT(script); 116 115 // Paper over https://bugs.webkit.org/show_bug.cgi?id=144050 117 if (! element)116 if (!script) 118 117 continue; 119 toScriptElementIfPossible(element.get())->execute(cachedScript); 118 auto* scriptElement = toScriptElementIfPossible(&script->element()); 119 ASSERT(scriptElement); 120 scriptElement->execute(script->cachedScript()); 120 121 m_document.decrementLoadEventDelayCount(); 121 122 } -
trunk/Source/WebCore/dom/ScriptRunner.h
r195243 r205218 57 57 58 58 Document& m_document; 59 Vector< PendingScript> m_scriptsToExecuteInOrder;60 Vector< PendingScript> m_scriptsToExecuteSoon; // http://www.whatwg.org/specs/web-apps/current-work/#set-of-scripts-that-will-execute-as-soon-as-possible61 HashMap<ScriptElement*, PendingScript> m_pendingAsyncScripts;59 Vector<Ref<PendingScript>> m_scriptsToExecuteInOrder; 60 Vector<RefPtr<PendingScript>> m_scriptsToExecuteSoon; // http://www.whatwg.org/specs/web-apps/current-work/#set-of-scripts-that-will-execute-as-soon-as-possible 61 HashMap<ScriptElement*, Ref<PendingScript>> m_pendingAsyncScripts; 62 62 Timer m_timer; 63 63 }; -
trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp
r202559 r205218 28 28 #include "HTMLDocumentParser.h" 29 29 30 #include "CachedScript.h" 30 31 #include "DocumentFragment.h" 31 32 #include "Frame.h" … … 501 502 } 502 503 503 void HTMLDocumentParser::watchForLoad( CachedResource* cachedScript)504 { 505 ASSERT(! cachedScript->isLoaded());506 // addClient would call notifyFinished if the load were complete.504 void HTMLDocumentParser::watchForLoad(PendingScript& pendingScript) 505 { 506 ASSERT(!pendingScript.isLoaded()); 507 // setClient would call notifyFinished if the load were complete. 507 508 // Callers do not expect to be re-entered from this call, so they should 508 // not an already-loaded CachedResource.509 cachedScript->addClient(this);510 } 511 512 void HTMLDocumentParser::stopWatchingForLoad( CachedResource* cachedScript)513 { 514 cachedScript->removeClient(this);509 // not an already-loaded PendingScript. 510 pendingScript.setClient(this); 511 } 512 513 void HTMLDocumentParser::stopWatchingForLoad(PendingScript& pendingScript) 514 { 515 pendingScript.clearClient(); 515 516 } 516 517 … … 522 523 } 523 524 524 void HTMLDocumentParser::notifyFinished( CachedResource* cachedResource)525 void HTMLDocumentParser::notifyFinished(PendingScript& pendingScript) 525 526 { 526 527 // pumpTokenizer can cause this parser to be detached from the Document, … … 535 536 } 536 537 537 m_scriptRunner->executeScriptsWaitingForLoad( cachedResource);538 m_scriptRunner->executeScriptsWaitingForLoad(pendingScript); 538 539 if (!isWaitingForScripts()) 539 540 resumeParsingAfterScriptExecution(); -
trunk/Source/WebCore/html/parser/HTMLDocumentParser.h
r197566 r205218 28 28 #define HTMLDocumentParser_h 29 29 30 #include "CachedResourceClient.h"31 30 #include "HTMLInputStream.h" 32 31 #include "HTMLScriptRunnerHost.h" 33 32 #include "HTMLSourceTracker.h" 34 33 #include "HTMLTokenizer.h" 34 #include "PendingScriptClient.h" 35 35 #include "ScriptableDocumentParser.h" 36 36 #include "XSSAuditor.h" … … 48 48 class PumpSession; 49 49 50 class HTMLDocumentParser : public ScriptableDocumentParser, private HTMLScriptRunnerHost, private CachedResourceClient {50 class HTMLDocumentParser : public ScriptableDocumentParser, private HTMLScriptRunnerHost, private PendingScriptClient { 51 51 WTF_MAKE_FAST_ALLOCATED; 52 52 public: … … 91 91 92 92 // HTMLScriptRunnerHost 93 void watchForLoad( CachedResource*) final;94 void stopWatchingForLoad( CachedResource*) final;93 void watchForLoad(PendingScript&) final; 94 void stopWatchingForLoad(PendingScript&) final; 95 95 HTMLInputStream& inputStream() final; 96 96 bool hasPreloadScanner() const final; 97 97 void appendCurrentInputStreamToPreloadScannerAndScan() final; 98 98 99 // CachedResourceClient100 void notifyFinished( CachedResource*) final;99 // PendingScriptClient 100 void notifyFinished(PendingScript&) final; 101 101 102 102 Document* contextForParsingSession(); -
trunk/Source/WebCore/html/parser/HTMLScriptRunner.cpp
r202105 r205218 59 59 { 60 60 // FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction? 61 if (m_parserBlockingScript.cachedScript() && m_parserBlockingScript.watchingForLoad()) 62 stopWatchingForLoad(m_parserBlockingScript); 61 if (m_parserBlockingScript) { 62 if (m_parserBlockingScript->watchingForLoad()) 63 stopWatchingForLoad(*m_parserBlockingScript); 64 } 63 65 64 66 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { 65 PendingScriptpendingScript = m_scriptsToExecuteAfterParsing.takeFirst();66 if (pendingScript .cachedScript() && pendingScript.watchingForLoad())67 auto pendingScript = m_scriptsToExecuteAfterParsing.takeFirst(); 68 if (pendingScript->watchingForLoad()) 67 69 stopWatchingForLoad(pendingScript); 68 70 } … … 96 98 } 97 99 errorOccurred = false; 98 return ScriptSourceCode(script.element() ->textContent(), documentURLForScriptExecution(m_document), script.startingPosition());100 return ScriptSourceCode(script.element().textContent(), documentURLForScriptExecution(m_document), script.startingPosition()); 99 101 } 100 102 … … 106 108 if (m_hasScriptsWaitingForStylesheets) 107 109 return false; 108 if (script. cachedScript() && !script.cachedScript()->isLoaded())110 if (script.needsLoading() && !script.isLoaded()) 109 111 return false; 110 112 return true; … … 116 118 ASSERT(!isExecutingScript()); 117 119 ASSERT(m_document->haveStylesheetsLoaded()); 118 ASSERT(isPendingScriptReady( m_parserBlockingScript));120 ASSERT(isPendingScriptReady(*m_parserBlockingScript)); 119 121 120 122 InsertionPointRecord insertionPointRecord(m_host.inputStream()); 121 executePendingScriptAndDispatchEvent( m_parserBlockingScript);122 } 123 124 void HTMLScriptRunner::executePendingScriptAndDispatchEvent( PendingScript&pendingScript)123 executePendingScriptAndDispatchEvent(WTFMove(m_parserBlockingScript)); 124 } 125 126 void HTMLScriptRunner::executePendingScriptAndDispatchEvent(RefPtr<PendingScript> pendingScript) 125 127 { 126 128 bool errorOccurred = false; 127 ScriptSourceCode sourceCode = sourceFromPendingScript( pendingScript, errorOccurred);129 ScriptSourceCode sourceCode = sourceFromPendingScript(*pendingScript, errorOccurred); 128 130 129 131 // Stop watching loads before executeScript to prevent recursion if the script reloads itself. 130 if (pendingScript .cachedScript() && pendingScript.watchingForLoad())131 stopWatchingForLoad( pendingScript);132 if (pendingScript->watchingForLoad()) 133 stopWatchingForLoad(*pendingScript); 132 134 133 135 if (!isExecutingScript()) 134 136 MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint(); 135 137 136 // Clear the pending script before possible rentrancy from executeScript() 137 RefPtr<Element> element = pendingScript.releaseElementAndClear(); 138 if (ScriptElement* scriptElement = toScriptElementIfPossible(element.get())) { 138 if (auto* scriptElement = toScriptElementIfPossible(&pendingScript->element())) { 139 139 NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); 140 140 IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document); … … 144 144 ASSERT(isExecutingScript()); 145 145 scriptElement->executeScript(sourceCode); 146 element->dispatchEvent(createScriptLoadEvent());146 pendingScript->element().dispatchEvent(createScriptLoadEvent()); 147 147 } 148 148 } … … 153 153 { 154 154 ASSERT(!pendingScript.watchingForLoad()); 155 m_host.watchForLoad(pendingScript.cachedScript()); 156 pendingScript.setWatchingForLoad(true); 155 m_host.watchForLoad(pendingScript); 157 156 } 158 157 … … 160 159 { 161 160 ASSERT(pendingScript.watchingForLoad()); 162 m_host.stopWatchingForLoad(pendingScript.cachedScript()); 163 pendingScript.setWatchingForLoad(false); 161 m_host.stopWatchingForLoad(pendingScript); 164 162 } 165 163 … … 188 186 bool HTMLScriptRunner::hasParserBlockingScript() const 189 187 { 190 return !!m_parserBlockingScript .element();188 return !!m_parserBlockingScript; 191 189 } 192 190 193 191 void HTMLScriptRunner::executeParsingBlockingScripts() 194 192 { 195 while (hasParserBlockingScript() && isPendingScriptReady( m_parserBlockingScript))193 while (hasParserBlockingScript() && isPendingScriptReady(*m_parserBlockingScript)) 196 194 executeParsingBlockingScript(); 197 195 } 198 196 199 void HTMLScriptRunner::executeScriptsWaitingForLoad( CachedResource* cachedScript)197 void HTMLScriptRunner::executeScriptsWaitingForLoad(PendingScript& pendingScript) 200 198 { 201 199 ASSERT(!isExecutingScript()); 202 200 ASSERT(hasParserBlockingScript()); 203 ASSERT_UNUSED( cachedScript, m_parserBlockingScript.cachedScript() == cachedScript);204 ASSERT(m_parserBlockingScript .cachedScript()->isLoaded());201 ASSERT_UNUSED(pendingScript, m_parserBlockingScript.get() == &pendingScript); 202 ASSERT(m_parserBlockingScript->isLoaded()); 205 203 executeParsingBlockingScripts(); 206 204 } … … 222 220 ASSERT(!isExecutingScript()); 223 221 ASSERT(!hasParserBlockingScript()); 224 ASSERT(m_scriptsToExecuteAfterParsing.first() .cachedScript());225 if (!m_scriptsToExecuteAfterParsing.first() .cachedScript()->isLoaded()) {222 ASSERT(m_scriptsToExecuteAfterParsing.first()->needsLoading()); 223 if (!m_scriptsToExecuteAfterParsing.first()->isLoaded()) { 226 224 watchForLoad(m_scriptsToExecuteAfterParsing.first()); 227 225 return false; 228 226 } 229 PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); 230 executePendingScriptAndDispatchEvent(first); 227 executePendingScriptAndDispatchEvent(m_scriptsToExecuteAfterParsing.takeFirst()); 231 228 // FIXME: What is this m_document check for? 232 229 if (!m_document) … … 236 233 } 237 234 235 static Ref<PendingScript> requestPendingScript(Element* script) 236 { 237 auto& scriptElement = *toScriptElementIfPossible(script); 238 ASSERT(scriptElement.willBeParserExecuted()); 239 ASSERT(scriptElement.cachedScript()); 240 return PendingScript::create(*script, *scriptElement.cachedScript()); 241 } 242 238 243 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) 239 244 { 240 if (!requestPendingScript(m_parserBlockingScript, element)) 241 return; 242 243 ASSERT(m_parserBlockingScript.cachedScript()); 245 ASSERT(!m_parserBlockingScript); 246 m_parserBlockingScript = requestPendingScript(element); 247 ASSERT(m_parserBlockingScript->needsLoading()); 244 248 245 249 // We only care about a load callback if cachedScript is not already 246 250 // in the cache. Callers will attempt to run the m_parserBlockingScript 247 251 // if possible before returning control to the parser. 248 if (!m_parserBlockingScript .cachedScript()->isLoaded())249 watchForLoad( m_parserBlockingScript);252 if (!m_parserBlockingScript->isLoaded()) 253 watchForLoad(*m_parserBlockingScript); 250 254 } 251 255 252 256 void HTMLScriptRunner::requestDeferredScript(Element* element) 253 257 { 254 PendingScript pendingScript; 255 if (!requestPendingScript(pendingScript, element)) 256 return; 257 258 ASSERT(pendingScript.cachedScript()); 259 m_scriptsToExecuteAfterParsing.append(pendingScript); 260 } 261 262 bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const 263 { 264 ASSERT(!pendingScript.element()); 265 pendingScript.setElement(script); 266 // This should correctly return 0 for empty or invalid srcValues. 267 CachedScript* cachedScript = toScriptElementIfPossible(script)->cachedScript().get(); 268 if (!cachedScript) { 269 notImplemented(); // Dispatch error event. 270 return false; 271 } 272 pendingScript.setCachedScript(cachedScript); 273 return true; 258 auto pendingScript = requestPendingScript(element); 259 ASSERT(pendingScript->needsLoading()); 260 m_scriptsToExecuteAfterParsing.append(WTFMove(pendingScript)); 274 261 } 275 262 … … 309 296 requestDeferredScript(script); 310 297 else if (scriptElement->readyToBeParserExecuted()) { 311 if (m_scriptNestingLevel == 1) { 312 m_parserBlockingScript.setElement(script); 313 m_parserBlockingScript.setStartingPosition(scriptStartPosition); 314 } else { 315 ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition); 316 scriptElement->executeScript(sourceCode); 317 } 298 if (m_scriptNestingLevel == 1) 299 m_parserBlockingScript = PendingScript::create(*script, scriptStartPosition); 300 else 301 scriptElement->executeScript(ScriptSourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition)); 318 302 } else 319 303 requestParsingBlockingScript(script); -
trunk/Source/WebCore/html/parser/HTMLScriptRunner.h
r162275 r205218 52 52 void execute(PassRefPtr<Element> scriptToProcess, const TextPosition& scriptStartPosition); 53 53 54 void executeScriptsWaitingForLoad( CachedResource*);54 void executeScriptsWaitingForLoad(PendingScript&); 55 55 bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; } 56 56 void executeScriptsWaitingForStylesheets(); … … 64 64 65 65 void executeParsingBlockingScript(); 66 void executePendingScriptAndDispatchEvent( PendingScript&);66 void executePendingScriptAndDispatchEvent(RefPtr<PendingScript>); 67 67 void executeParsingBlockingScripts(); 68 68 69 69 void requestParsingBlockingScript(Element*); 70 70 void requestDeferredScript(Element*); 71 bool requestPendingScript(PendingScript&, Element*) const;72 71 73 72 void runScript(Element*, const TextPosition& scriptStartPosition); … … 81 80 Document* m_document; 82 81 HTMLScriptRunnerHost& m_host; 83 PendingScriptm_parserBlockingScript;84 Deque< PendingScript> m_scriptsToExecuteAfterParsing; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing82 RefPtr<PendingScript> m_parserBlockingScript; 83 Deque<Ref<PendingScript>> m_scriptsToExecuteAfterParsing; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing 85 84 unsigned m_scriptNestingLevel; 86 85 -
trunk/Source/WebCore/html/parser/HTMLScriptRunnerHost.h
r95901 r205218 31 31 namespace WebCore { 32 32 33 class CachedResource;34 33 class Element; 35 34 class HTMLInputStream; 35 class PendingScript; 36 36 class ScriptSourceCode; 37 37 … … 41 41 42 42 // Implementors should call cachedResource->addClient() here or soon after. 43 virtual void watchForLoad( CachedResource*) = 0;43 virtual void watchForLoad(PendingScript&) = 0; 44 44 // Implementors must call cachedResource->removeClient() immediately. 45 virtual void stopWatchingForLoad( CachedResource*) = 0;45 virtual void stopWatchingForLoad(PendingScript&) = 0; 46 46 47 47 virtual HTMLInputStream& inputStream() = 0;
Note: See TracChangeset
for help on using the changeset viewer.