Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     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.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/dom/ScriptRunner.h"
     28 
     29 #include "core/dom/Document.h"
     30 #include "core/dom/Element.h"
     31 #include "core/dom/PendingScript.h"
     32 #include "core/dom/ScriptLoader.h"
     33 #include "core/fetch/ScriptResource.h"
     34 #include "platform/heap/Handle.h"
     35 
     36 namespace WebCore {
     37 
     38 ScriptRunner::ScriptRunner(Document* document)
     39     : m_document(document)
     40     , m_timer(this, &ScriptRunner::timerFired)
     41 {
     42     ASSERT(document);
     43 }
     44 
     45 ScriptRunner::~ScriptRunner()
     46 {
     47 }
     48 
     49 void ScriptRunner::queueScriptForExecution(ScriptLoader* scriptLoader, ResourcePtr<ScriptResource> resource, ExecutionType executionType)
     50 {
     51     ASSERT(scriptLoader);
     52     ASSERT(resource.get());
     53 
     54     Element* element = scriptLoader->element();
     55     ASSERT(element);
     56     ASSERT(element->inDocument());
     57 
     58     m_document->incrementLoadEventDelayCount();
     59 
     60     switch (executionType) {
     61     case ASYNC_EXECUTION:
     62         m_pendingAsyncScripts.add(scriptLoader, PendingScript(element, resource.get()));
     63         break;
     64 
     65     case IN_ORDER_EXECUTION:
     66         m_scriptsToExecuteInOrder.append(PendingScript(element, resource.get()));
     67         break;
     68     }
     69 }
     70 
     71 void ScriptRunner::suspend()
     72 {
     73     m_timer.stop();
     74 }
     75 
     76 void ScriptRunner::resume()
     77 {
     78     if (hasPendingScripts())
     79         m_timer.startOneShot(0, FROM_HERE);
     80 }
     81 
     82 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType executionType)
     83 {
     84     switch (executionType) {
     85     case ASYNC_EXECUTION:
     86         ASSERT(m_pendingAsyncScripts.contains(scriptLoader));
     87         m_scriptsToExecuteSoon.append(m_pendingAsyncScripts.take(scriptLoader));
     88         break;
     89 
     90     case IN_ORDER_EXECUTION:
     91         ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
     92         break;
     93     }
     94     m_timer.startOneShot(0, FROM_HERE);
     95 }
     96 
     97 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionType executionType)
     98 {
     99     switch (executionType) {
    100     case ASYNC_EXECUTION:
    101         ASSERT(m_pendingAsyncScripts.contains(scriptLoader));
    102         m_pendingAsyncScripts.remove(scriptLoader);
    103         m_document->decrementLoadEventDelayCount();
    104         break;
    105 
    106     case IN_ORDER_EXECUTION:
    107         ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
    108         break;
    109     }
    110 }
    111 
    112 void ScriptRunner::timerFired(Timer<ScriptRunner>* timer)
    113 {
    114     ASSERT_UNUSED(timer, timer == &m_timer);
    115 
    116     RefPtrWillBeRawPtr<Document> protect(m_document.get());
    117 
    118     Vector<PendingScript> scripts;
    119     scripts.swap(m_scriptsToExecuteSoon);
    120 
    121     size_t numInOrderScriptsToExecute = 0;
    122     for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute].resource()->isLoaded(); ++numInOrderScriptsToExecute)
    123         scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute]);
    124     if (numInOrderScriptsToExecute)
    125         m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute);
    126 
    127     size_t size = scripts.size();
    128     for (size_t i = 0; i < size; ++i) {
    129         ScriptResource* resource = scripts[i].resource();
    130         RefPtrWillBeRawPtr<Element> element = scripts[i].releaseElementAndClear();
    131         toScriptLoaderIfPossible(element.get())->execute(resource);
    132         m_document->decrementLoadEventDelayCount();
    133     }
    134 }
    135 
    136 void ScriptRunner::trace(Visitor* visitor)
    137 {
    138     visitor->trace(m_document);
    139     visitor->trace(m_scriptsToExecuteInOrder);
    140     visitor->trace(m_scriptsToExecuteSoon);
    141     visitor->trace(m_pendingAsyncScripts);
    142 }
    143 
    144 }
    145