// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
{
    if (m_alreadyStarted)
        return false;

    ScriptLoaderClient* client = this->client();

    bool wasParserInserted;
    if (m_parserInserted) {
        wasParserInserted = true;
        m_parserInserted = false;
    } else {
        wasParserInserted = false;
    }

    if (wasParserInserted && !client->asyncAttributeValue())
        m_forceAsync = true;

    // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
    if (!client->hasSourceAttribute() && !m_element->hasChildren())
        return false;

    if (!m_element->inDocument())
        return false;

    if (!isScriptTypeSupported(supportLegacyTypes))
        return false;

    if (wasParserInserted) {
        m_parserInserted = true;
        m_forceAsync = false;
    }

    m_alreadyStarted = true;

    // FIXME: If script is parser inserted, verify it's still in the original document.
    Document& elementDocument = m_element->document();
    Document* contextDocument = elementDocument.contextDocument().get();

    if (!contextDocument || !contextDocument->allowExecutingScripts(m_element))
        return false;

    if (!isScriptForEventSupported())
        return false;

    if (!client->charsetAttributeValue().isEmpty())
        m_characterEncoding = client->charsetAttributeValue();
    else
        m_characterEncoding = elementDocument.characterSet();

    if (client->hasSourceAttribute()) {
        FetchRequest::DeferOption defer = FetchRequest::NoDefer;
        if (!m_parserInserted || client->asyncAttributeValue() || client->deferAttributeValue())
            defer = FetchRequest::LazyLoad;
        if (!fetchScript(client->sourceAttributeValue(), defer))
            return false;
    }

    if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parserInserted && !client->asyncAttributeValue()) {
        m_willExecuteWhenDocumentFinishedParsing = true;
        m_willBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyncAttributeValue()) {
        m_willBeParserExecuted = true;
    } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocument.isRenderingReady()) {
        m_willBeParserExecuted = true;
        m_readyToBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) {
        m_willExecuteInOrder = true;
        m_pendingScript = PendingScript(m_element, m_resource.get());
        contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRunner::IN_ORDER_EXECUTION);
        // Note that watchForLoad can immediately call notifyFinished.
        m_pendingScript.watchForLoad(this);
    } else if (client->hasSourceAttribute()) {
        m_pendingScript = PendingScript(m_element, m_resource.get());
        LocalFrame* frame = m_element->document().frame();
        if (frame) {
            ScriptState* scriptState = ScriptState::forMainWorld(frame);
            if (scriptState->contextIsValid())
                ScriptStreamer::startStreaming(m_pendingScript, PendingScript::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTaskRunner());
        }
        contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRunner::ASYNC_EXECUTION);
        // Note that watchForLoad can immediately call notifyFinished.
        m_pendingScript.watchForLoad(this);
    } else {
        // Reset line numbering for nested writes.
        TextPosition position = elementDocument.isInDocumentWrite() ? TextPosition() : scriptStartPosition;
        KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInserted) ? elementDocument.url() : KURL();
        if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position))) {
            dispatchErrorEvent();
            return false;
        }
    }

    return true;
}
Beispiel #2
0
// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
{
    if (m_alreadyStarted)
        return false;

    bool wasParserInserted;
    if (m_parserInserted) {
        wasParserInserted = true;
        m_parserInserted = false;
    } else
        wasParserInserted = false;

    if (wasParserInserted && !asyncAttributeValue())
        m_forceAsync = true;

    // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
    if (!hasSourceAttribute() && !m_element->firstChild())
        return false;

    if (!m_element->inDocument())
        return false;

    if (!isScriptTypeSupported(supportLegacyTypes))
        return false;

    if (wasParserInserted) {
        m_parserInserted = true;
        m_forceAsync = false;
    }

    m_alreadyStarted = true;

    // FIXME: If script is parser inserted, verify it's still in the original document.
    Document* document = m_element->document();

    // FIXME: Eventually we'd like to evaluate scripts which are inserted into a
    // viewless document but this'll do for now.
    // See http://bugs.webkit.org/show_bug.cgi?id=5727
    if (!document->frame())
        return false;

    if (!document->frame()->script()->canExecuteScripts(AboutToExecuteScript))
        return false;

    if (!isScriptForEventSupported())
        return false;

    if (!charsetAttributeValue().isEmpty())
        m_characterEncoding = charsetAttributeValue();
    else
        m_characterEncoding = document->charset();

    if (hasSourceAttribute())
        if (!requestScript(sourceAttributeValue()))
            return false;

    if (hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) {
        m_willExecuteWhenDocumentFinishedParsing = true;
        m_willBeParserExecuted = true;
    } else if (hasSourceAttribute() && m_parserInserted && !asyncAttributeValue())
        m_willBeParserExecuted = true;
    else if (!hasSourceAttribute() && m_parserInserted && !document->haveStylesheetsLoaded()) {
        m_willBeParserExecuted = true;
        m_readyToBeParserExecuted = true;
    } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) {
        m_willExecuteInOrder = true;
        document->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION);
        m_cachedScript->addClient(this);
    } else if (hasSourceAttribute()) {
        m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION);
        m_cachedScript->addClient(this);
    } else {
        // Reset line numbering for nested writes.
        TextPosition position = document->isInDocumentWrite() ? TextPosition() : scriptStartPosition;
        executeScript(ScriptSourceCode(scriptContent(), document->url(), position));
    }

    return true;
}
Beispiel #3
0
// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
                                 LegacyTypeSupport supportLegacyTypes) {
    if (m_alreadyStarted)
        return false;

    ScriptLoaderClient* client = this->client();

    bool wasParserInserted;
    if (m_parserInserted) {
        wasParserInserted = true;
        m_parserInserted = false;
    } else {
        wasParserInserted = false;
    }

    if (wasParserInserted && !client->asyncAttributeValue())
        m_forceAsync = true;

    // FIXME: HTML5 spec says we should check that all children are either
    // comments or empty text nodes.
    if (!client->hasSourceAttribute() && !m_element->hasChildren())
        return false;

    if (!m_element->isConnected())
        return false;

    if (!isScriptTypeSupported(supportLegacyTypes))
        return false;

    if (wasParserInserted) {
        m_parserInserted = true;
        m_forceAsync = false;
    }

    m_alreadyStarted = true;

    // FIXME: If script is parser inserted, verify it's still in the original
    // document.
    Document& elementDocument = m_element->document();
    Document* contextDocument = elementDocument.contextDocument();

    if (!contextDocument || !contextDocument->allowExecutingScripts(m_element))
        return false;

    if (!isScriptForEventSupported())
        return false;

    if (!client->charsetAttributeValue().isEmpty())
        m_characterEncoding = client->charsetAttributeValue();
    else
        m_characterEncoding = elementDocument.characterSet();

    if (client->hasSourceAttribute()) {
        FetchRequest::DeferOption defer = FetchRequest::NoDefer;
        if (!m_parserInserted || client->asyncAttributeValue() ||
                client->deferAttributeValue())
            defer = FetchRequest::LazyLoad;
        if (m_documentWriteIntervention ==
                DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle)
            defer = FetchRequest::IdleLoad;
        if (!fetchScript(client->sourceAttributeValue(), defer))
            return false;
    }

    // Since the asynchronous, low priority fetch for doc.written blocked
    // script is not for execution, return early from here. Watch for its
    // completion to be able to remove it from the memory cache.
    if (m_documentWriteIntervention ==
            DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) {
        m_pendingScript = PendingScript::create(m_element, m_resource.get());
        m_pendingScript->watchForLoad(this);
        return true;
    }

    if (client->hasSourceAttribute() && client->deferAttributeValue() &&
            m_parserInserted && !client->asyncAttributeValue()) {
        m_willExecuteWhenDocumentFinishedParsing = true;
        m_willBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && m_parserInserted &&
               !client->asyncAttributeValue()) {
        m_willBeParserExecuted = true;
    } else if (!client->hasSourceAttribute() && m_parserInserted &&
               !elementDocument.isScriptExecutionReady()) {
        m_willBeParserExecuted = true;
        m_readyToBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() &&
               !m_forceAsync) {
        m_pendingScript = PendingScript::create(m_element, m_resource.get());
        m_asyncExecType = ScriptRunner::InOrder;
        contextDocument->scriptRunner()->queueScriptForExecution(this,
                m_asyncExecType);
        // Note that watchForLoad can immediately call notifyFinished.
        m_pendingScript->watchForLoad(this);
    } else if (client->hasSourceAttribute()) {
        m_pendingScript = PendingScript::create(m_element, m_resource.get());
        m_asyncExecType = ScriptRunner::Async;
        LocalFrame* frame = m_element->document().frame();
        if (frame) {
            ScriptState* scriptState = ScriptState::forMainWorld(frame);
            if (scriptState)
                ScriptStreamer::startStreaming(
                    m_pendingScript.get(), ScriptStreamer::Async, frame->settings(),
                    scriptState, frame->frameScheduler()->loadingTaskRunner());
        }
        contextDocument->scriptRunner()->queueScriptForExecution(this,
                m_asyncExecType);
        // Note that watchForLoad can immediately call notifyFinished.
        m_pendingScript->watchForLoad(this);
    } else {
        // Reset line numbering for nested writes.
        TextPosition position = elementDocument.isInDocumentWrite()
                                ? TextPosition()
                                : scriptStartPosition;
        KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInserted)
                         ? elementDocument.url()
                         : KURL();
        if (!executeScript(
                    ScriptSourceCode(scriptContent(), scriptURL, position))) {
            dispatchErrorEvent();
            return false;
        }
    }

    return true;
}
Beispiel #4
0
// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
{
    if (m_alreadyStarted)
        return false;

    ScriptLoaderClient* client = this->client();

    bool wasParserInserted;
    if (m_parserInserted) {
        wasParserInserted = true;
        m_parserInserted = false;
    } else {
        wasParserInserted = false;
    }

    if (wasParserInserted && !client->asyncAttributeValue())
        m_forceAsync = true;

    // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
    if (!client->hasSourceAttribute() && !m_element->firstChild())
        return false;

    if (!m_element->inDocument())
        return false;

    if (!isScriptTypeSupported(supportLegacyTypes))
        return false;

    if (wasParserInserted) {
        m_parserInserted = true;
        m_forceAsync = false;
    }

    m_alreadyStarted = true;

    // FIXME: If script is parser inserted, verify it's still in the original document.
    Document& elementDocument = m_element->document();
    Document* contextDocument = elementDocument.contextDocument().get();

    if (!contextDocument || !contextDocument->allowExecutingScripts(m_element))
        return false;

    if (!isScriptForEventSupported())
        return false;

    if (!client->charsetAttributeValue().isEmpty())
        m_characterEncoding = client->charsetAttributeValue();
    else
        m_characterEncoding = elementDocument.charset();

    if (client->hasSourceAttribute()) {
        if (!fetchScript(client->sourceAttributeValue()))
            return false;
    }

    if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parserInserted && !client->asyncAttributeValue()) {
        m_willExecuteWhenDocumentFinishedParsing = true;
        m_willBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyncAttributeValue()) {
        m_willBeParserExecuted = true;
    } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocument.isRenderingReady()) {
        m_willBeParserExecuted = true;
        m_readyToBeParserExecuted = true;
    } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) {
        m_willExecuteInOrder = true;
        contextDocument->scriptRunner()->queueScriptForExecution(this, m_resource, ScriptRunner::IN_ORDER_EXECUTION);
        m_resource->addClient(this);
    } else if (client->hasSourceAttribute()) {
        contextDocument->scriptRunner()->queueScriptForExecution(this, m_resource, ScriptRunner::ASYNC_EXECUTION);
        m_resource->addClient(this);
    } else {
        // Reset line numbering for nested writes.
        TextPosition position = elementDocument.isInDocumentWrite() ? TextPosition() : scriptStartPosition;
        KURL scriptURL = (!elementDocument.isInDocumentWrite() && m_parserInserted) ? elementDocument.url() : KURL();
        executeScript(ScriptSourceCode(scriptContent(), scriptURL, position));
    }

    return true;
}