Index: sky/engine/core/html/parser/HTMLScriptRunner.cpp |
diff --git a/sky/engine/core/html/parser/HTMLScriptRunner.cpp b/sky/engine/core/html/parser/HTMLScriptRunner.cpp |
index b79a9008b631de3bb91d0840e9eab2d2ac97027f..e0bab6300dbe993013f914b7da15ae6703902889 100644 |
--- a/sky/engine/core/html/parser/HTMLScriptRunner.cpp |
+++ b/sky/engine/core/html/parser/HTMLScriptRunner.cpp |
@@ -5,6 +5,7 @@ |
#include "sky/engine/config.h" |
#include "sky/engine/core/html/parser/HTMLScriptRunner.h" |
+#include "base/bind.h" |
#include "sky/engine/core/app/AbstractModule.h" |
#include "sky/engine/core/dom/Document.h" |
#include "sky/engine/core/dom/Microtask.h" |
@@ -14,36 +15,111 @@ |
namespace blink { |
-HTMLScriptRunner::HTMLScriptRunner() |
- : m_isExecutingScript(false) |
-{ |
+PassOwnPtr<HTMLScriptRunner> HTMLScriptRunner::createForScript( |
+ PassRefPtr<HTMLScriptElement> element, |
+ TextPosition position, |
+ HTMLScriptRunnerHost* host) { |
+ return adoptPtr(new HTMLScriptRunner(element, position, host)); |
+} |
+ |
+HTMLScriptRunner::HTMLScriptRunner(PassRefPtr<HTMLScriptElement> element, |
+ TextPosition position, |
+ HTMLScriptRunnerHost* host) |
+ : m_host(host), |
+ m_element(element), |
+ m_position(position), |
+ m_state(StateInitial), |
+ m_weakFactory(this) { |
} |
HTMLScriptRunner::~HTMLScriptRunner() |
{ |
+ // If we hit this ASSERT we failed to notify the ScriptRunnerHost! |
+ ASSERT(m_state == StateCompleted); |
} |
-void HTMLScriptRunner::runScript(PassRefPtr<HTMLScriptElement> element, TextPosition textPosition) |
-{ |
- ASSERT(element->document().haveImportsLoaded()); |
- Microtask::performCheckpoint(); |
+bool HTMLScriptRunner::isExecutingScript() const { |
+ return m_state == StateExecuting; |
+} |
- Document& sourceDocument = element->document(); |
- String source = element->textContent(); |
+void HTMLScriptRunner::advanceTo(State state, AdvanceType advanceType) { |
+ if (advanceType == ExecutionNormal) { |
+ switch (m_state) { |
+ case StateInitial: |
+ ASSERT(state == StateLoading); |
+ break; |
+ case StateLoading: |
+ ASSERT(state == StateExecuting); |
+ break; |
+ case StateExecuting: |
+ ASSERT(state == StateCompleted); |
+ break; |
+ case StateCompleted: |
+ ASSERT_NOT_REACHED(); |
+ } |
+ } |
+ m_state = state; |
- RefPtr<Document> contextDocument = sourceDocument.contextDocument().get(); |
+ if (m_state == StateCompleted) |
+ m_host->scriptExecutionCompleted(); |
+ // We may be deleted by scriptExecutionCompleted(). |
+} |
+ |
+static LocalFrame* contextFrame(Element* element) { |
+ Document* contextDocument = element->document().contextDocument().get(); |
if (!contextDocument) |
- return; |
+ return nullptr; |
LocalFrame* frame = contextDocument->frame(); |
if (!frame) |
- return; |
+ return nullptr; |
+ return frame; |
+} |
+ |
+void HTMLScriptRunner::scriptFailed() { |
+ advanceTo(StateCompleted, ExecutionFailure); |
+} |
- ASSERT(!m_isExecutingScript); |
- TemporaryChange<bool> executingScript(m_isExecutingScript, true); |
+void HTMLScriptRunner::start() { |
+ ASSERT(m_state == StateInitial); |
+ ASSERT(m_element->document().haveImportsLoaded()); |
+ |
+ Document& sourceDocument = m_element->document(); |
+ String source = m_element->textContent(); |
+ |
+ LocalFrame* frame = contextFrame(m_element.get()); |
+ if (!frame) |
+ return scriptFailed(); |
+ |
+ advanceTo(StateLoading); |
ASSERT(sourceDocument.module()); |
- frame->dart().LoadModule(sourceDocument.module(), source, textPosition); |
+ DartController::LoadFinishedCallback loadFinished = base::Bind( |
+ &HTMLScriptRunner::executeLibrary, m_weakFactory.GetWeakPtr()); |
+ frame->dart().LoadScriptInModule(sourceDocument.module(), source, |
+ m_position, loadFinished); |
+} |
+ |
+// Enforce that the caller holds refs using RefPtr. |
+// FIXME: Neither of these should need refs, the Script should hold onto the |
+// library the document should keep the Module alive. |
+void HTMLScriptRunner::executeLibrary(RefPtr<AbstractModule> module, |
+ RefPtr<DartValue> library) { |
+ if (!module) |
+ return scriptFailed(); |
+ |
+ advanceTo(StateExecuting); |
+ |
+ // Ian says we'll remove microtasks, but for now execute them right before |
+ // we "run" the script (call 'init'), not at dependency resolution |
+ // or script failures, etc. |
+ Microtask::performCheckpoint(); |
+ |
+ if (LocalFrame* frame = contextFrame(m_element.get())) |
+ frame->dart().ExecuteLibraryInModule(module.get(), library->dart_value()); |
+ |
+ advanceTo(StateCompleted); |
+ // We may be deleted at this point. |
} |
} |