void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript, PendingScriptType pendingScriptType)
{
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);

    // Stop watching loads before executeScript to prevent recursion if the script reloads itself.
    if (pendingScript.resource() && pendingScript.watchingForLoad())
        stopWatchingForLoad(pendingScript);

    if (!isExecutingScript()) {
        Microtask::performCheckpoint();
        if (pendingScriptType == PendingScriptBlockingParser) {
            m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady();
            // The parser cannot be unblocked as a microtask requested another resource
            if (m_hasScriptsWaitingForResources)
                return;
        }
    }

    // Clear the pending script before possible rentrancy from executeScript()
    RefPtr<Element> element = pendingScript.releaseElementAndClear();
    if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element.get())) {
        NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
        IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
        if (errorOccurred)
            scriptLoader->dispatchErrorEvent();
        else {
            ASSERT(isExecutingScript());
            scriptLoader->executeScript(sourceCode);
            element->dispatchEvent(createScriptLoadEvent());
        }
    }
    ASSERT(!isExecutingScript());
}
Exemple #2
0
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
{
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);

    // Stop watching loads before executeScript to prevent recursion if the script reloads itself.
    if (pendingScript.cachedScript() && pendingScript.watchingForLoad())
        stopWatchingForLoad(pendingScript);

    if (!isExecutingScript()) {
#if ENABLE(CUSTOM_ELEMENTS)
        CustomElementRegistry::deliverAllLifecycleCallbacks();
#endif
        MutationObserver::deliverAllMutations();
    }

    // Clear the pending script before possible rentrancy from executeScript()
    RefPtr<Element> element = pendingScript.releaseElementAndClear();
    if (ScriptElement* scriptElement = toScriptElement(element.get())) {
        NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
        IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
        if (errorOccurred)
            scriptElement->dispatchErrorEvent();
        else {
            ASSERT(isExecutingScript());
            scriptElement->executeScript(sourceCode);
            element->dispatchEvent(createScriptLoadEvent());
        }
    }
    ASSERT(!isExecutingScript());
}
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
{
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);

    // Stop watching loads before executeScript to prevent recursion if the script reloads itself.
    if (pendingScript.resource() && pendingScript.watchingForLoad())
        stopWatchingForLoad(pendingScript);

    if (!isExecutingScript())
        Microtask::performCheckpoint();

    // Clear the pending script before possible rentrancy from executeScript()
    RefPtr<Element> element = pendingScript.releaseElementAndClear();
    if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element.get())) {
        NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
        IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
        if (errorOccurred)
            scriptLoader->dispatchErrorEvent();
        else {
            ASSERT(isExecutingScript());
            scriptLoader->executeScript(sourceCode);
            element->dispatchEvent(createScriptLoadEvent());
        }
    }
    ASSERT(!isExecutingScript());
}
void HTMLDocumentParser::watchForLoad(PendingScript& pendingScript)
{
    ASSERT(!pendingScript.isLoaded());
    // setClient would call notifyFinished if the load were complete.
    // Callers do not expect to be re-entered from this call, so they should
    // not an already-loaded PendingScript.
    pendingScript.setClient(this);
}
bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
{
    m_hasScriptsWaitingForResources = !m_document->haveStylesheetsAndImportsLoaded();
    if (m_hasScriptsWaitingForResources)
        return false;
    if (script.resource() && !script.resource()->isLoaded())
        return false;
    return true;
}
bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
{
    m_hasScriptsWaitingForStylesheets = !m_document->haveStylesheetsLoaded();
    if (m_hasScriptsWaitingForStylesheets)
        return false;
    if (script.cachedScript() && !script.cachedScript()->isLoaded())
        return false;
    return true;
}
void HTMLScriptRunner::requestDeferredScript(Element* element)
{
    PendingScript pendingScript;
    if (!requestPendingScript(pendingScript, element))
        return;

    ASSERT(pendingScript.cachedScript());
    m_scriptsToExecuteAfterParsing.append(pendingScript);
}
bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
{
    m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady();
    if (m_hasScriptsWaitingForResources)
        return false;
    if (script.resource() && !script.resource()->isLoaded())
        return false;
    return true;
}
Exemple #9
0
void ScriptElement::executeScriptForScriptRunner(PendingScript& pendingScript)
{
    if (auto* loadableScript = pendingScript.loadableScript())
        executeScriptAndDispatchEvent(*loadableScript);
    else {
        ASSERT(!pendingScript.wasErrored());
        executeScript(ScriptSourceCode(scriptContent(), m_element.document().url(), pendingScript.startingPosition()));
        dispatchLoadEvent();
    }
}
ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& script, bool& errorOccurred) const
{
    if (script.cachedScript()) {
        errorOccurred = script.cachedScript()->errorOccurred();
        ASSERT(script.cachedScript()->isLoaded());
        return ScriptSourceCode(script.cachedScript());
    }
    errorOccurred = false;
    return ScriptSourceCode(script.element()->textContent(), documentURLForScriptExecution(m_document), script.startingPosition());
}
Exemple #11
0
void ScriptRunner::notifyFinished(PendingScript& pendingScript)
{
    if (pendingScript.element().willExecuteInOrder())
        ASSERT(!m_scriptsToExecuteInOrder.isEmpty());
    else {
        ASSERT(m_pendingAsyncScripts.contains(pendingScript));
        m_scriptsToExecuteSoon.append(m_pendingAsyncScripts.take(pendingScript)->ptr());
    }
    pendingScript.clearClient();
    m_timer.startOneShot(0);
}
HTMLScriptRunner::~HTMLScriptRunner()
{
    // FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction?
    if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
        stopWatchingForLoad(m_parsingBlockingScript);

    while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
        PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst();
        if (pendingScript.cachedScript() && pendingScript.watchingForLoad())
            stopWatchingForLoad(pendingScript);
    }
}
bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
{
    ASSERT(!pendingScript.element());
    pendingScript.setElement(script);
    // This should correctly return 0 for empty or invalid srcValues.
    CachedScript* cachedScript = toScriptElement(script)->cachedScript().get();
    if (!cachedScript) {
        notImplemented(); // Dispatch error event.
        return false;
    }
    pendingScript.setCachedScript(cachedScript);
    return true;
}
bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
{
    ASSERT(!pendingScript.element());
    pendingScript.setElement(script);
    // This should correctly return 0 for empty or invalid srcValues.
    ScriptResource* resource = toScriptLoaderIfPossible(script)->resource().get();
    if (!resource) {
        notImplemented(); // Dispatch error event.
        return false;
    }
    pendingScript.setScriptResource(resource);
    return true;
}
Exemple #15
0
void HTMLScriptRunner::detach()
{
    if (!m_document)
        return;

    m_parserBlockingScript->stopWatchingForLoad();
    m_parserBlockingScript->releaseElementAndClear();

    while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
        PendingScript* pendingScript = m_scriptsToExecuteAfterParsing.takeFirst();
        pendingScript->stopWatchingForLoad();
        pendingScript->releaseElementAndClear();
    }
    m_document = nullptr;
}
Exemple #16
0
void HTMLScriptRunner::requestDeferredScript(Element* element)
{
    PendingScript* pendingScript = PendingScript::create(nullptr, nullptr);
    if (!requestPendingScript(pendingScript, element))
        return;

    if (m_document->frame() && !pendingScript->isReady()) {
        ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame());
        if (scriptState)
            ScriptStreamer::startStreaming(pendingScript, ScriptStreamer::Deferred, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner());
    }

    ASSERT(pendingScript->resource());
    m_scriptsToExecuteAfterParsing.append(pendingScript);
}
Exemple #17
0
PendingScript::PendingScript(const PendingScript& other)
    : ResourceOwner(other)
    , m_watchingForLoad(other.m_watchingForLoad)
    , m_element(other.m_element)
    , m_startingPosition(other.m_startingPosition)
    , m_streamer(other.m_streamer)
{
    setScriptResource(other.resource());
}
bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
{
    ASSERT(!pendingScript.element());
    const AtomicString& srcValue = script->getAttribute(srcAttr);
    // Allow the host to disllow script loads (using the XSSAuditor, etc.)
    if (!m_host->shouldLoadExternalScriptFromSrc(srcValue))
        return false;
    // FIXME: We need to resolve the url relative to the element.
    if (!script->dispatchBeforeLoadEvent(srcValue))
        return false;
    pendingScript.adoptElement(script);
    // This should correctly return 0 for empty or invalid srcValues.
    CachedScript* cachedScript = m_document->cachedResourceLoader()->requestScript(srcValue, toScriptElement(script)->scriptCharset());
    if (!cachedScript) {
        notImplemented(); // Dispatch error event.
        return false;
    }
    pendingScript.setCachedScript(cachedScript);
    return true;
}
Exemple #19
0
bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* settings, ScriptState* scriptState, PendingScript::Type scriptType)
{
    ASSERT(isMainThread());
    if (!settings || !settings->v8ScriptStreamingEnabled())
        return false;
    if (settings->v8ScriptStreamingMode() == ScriptStreamingModeOnlyAsyncAndDefer
        && scriptType == PendingScript::ParsingBlocking)
        return false;

    ScriptResource* resource = script.resource();
    if (resource->isLoaded())
        return false;
    if (!resource->url().protocolIsInHTTPFamily())
        return false;
    if (resource->resourceToRevalidate()) {
        // This happens e.g., during reloads. We're actually not going to load
        // the current Resource of the PendingScript but switch to another
        // Resource -> don't stream.
        return false;
    }
    // We cannot filter out short scripts, even if we wait for the HTTP headers
    // to arrive. In general, the web servers don't seem to send the
    // Content-Length HTTP header for scripts.

    if (!scriptState->contextIsValid())
        return false;

    // Decide what kind of cached data we should produce while streaming. By
    // default, we generate the parser cache for streamed scripts, to emulate
    // the non-streaming behavior (see V8ScriptRunner::compileScript).
    v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProduceParserCache;
    if (settings->v8CacheOptions() == V8CacheOptionsCode)
        compileOption = v8::ScriptCompiler::kProduceCodeCache;

    // The Resource might go out of scope if the script is no longer
    // needed. This makes PendingScript notify the ScriptStreamer when it is
    // destroyed.
    script.setStreamer(adoptRef(new ScriptStreamer(resource, scriptType, settings->v8ScriptStreamingMode(), scriptState, compileOption)));

    return true;
}
Exemple #20
0
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
{
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);

    // Stop watching loads before executeScript to prevent recursion if the script reloads itself.
    if (pendingScript.cachedScript() && pendingScript.watchingForLoad())
        stopWatchingForLoad(pendingScript);

    // WebERA: Insert HB relation between the execution of a pending script and the load of the script
    if (HBIsCurrentEventActionValid() && pendingScript.cachedScript() && pendingScript.cachedScript()->isLoaded() && pendingScript.cachedScript()->getLoadingEventAction() != 0) {
        HBAddExplicitArc(pendingScript.cachedScript()->getLoadingEventAction(), HBCurrentEventAction());
    }

    // Clear the pending script before possible rentrancy from executeScript()
    RefPtr<Element> element = pendingScript.releaseElementAndClear();
    if (ScriptElement* scriptElement = toScriptElement(element.get())) {
        NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
        IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
        if (errorOccurred)
            scriptElement->dispatchErrorEvent();
        else {
            ASSERT(isExecutingScript());
            scriptElement->executeScript(sourceCode);
            element->dispatchEvent(createScriptLoadEvent());
        }
    }
    ASSERT(!m_scriptNestingLevel);
}
Exemple #21
0
bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
{
    ASSERT(!pendingScript.element());
	if (V8IsolatedContext::getEntered() != 0)
	{
		std::ostringstream wid;
		int worldID = V8IsolatedContext::getEntered()->getWorldID();
		wid << worldID;
		std::string aclid = wid.str()+";";
		std::string aclname = "ACL";
		std::string ROACLname = "ROACL";
		ExceptionCode ec;
		if (worldID!=0)
		{
			script->setAttribute("worldID",wid.str().c_str(),ec,worldID,false);
			script->setAttribute(aclname.c_str(),aclid.c_str(),ec,worldID,false);
			script->setAttribute(ROACLname.c_str(),aclid.c_str(),ec,worldID,false);
		}
	}
    const AtomicString& srcValue = script->getAttribute(srcAttr);
    // Allow the host to disllow script loads (using the XSSAuditor, etc.)
    if (!m_host->shouldLoadExternalScriptFromSrc(srcValue))
        return false;
    // FIXME: We need to resolve the url relative to the element.
    if (!script->dispatchBeforeLoadEvent(srcValue))
        return false;
    pendingScript.adoptElement(script);
    // This should correctly return 0 for empty or invalid srcValues.
    CachedScript* cachedScript = m_document->docLoader()->requestScript(srcValue, toScriptElement(script)->scriptCharset());
    if (!cachedScript) {
        notImplemented(); // Dispatch error event.
        return false;
    }
    pendingScript.setCachedScript(cachedScript);
    return true;
}
Exemple #22
0
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
{
    bool errorOccurred = false;
    ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);

    // Clear the pending script before possible rentrancy from executeScript()
    RefPtr<Element> scriptElement = pendingScript.releaseElementAndClear();
    {
        NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
        if (errorOccurred)
            scriptElement->dispatchEvent(createScriptErrorEvent());
        else 
		{
            executeScript(scriptElement.get(), sourceCode);
            scriptElement->dispatchEvent(createScriptLoadEvent());
        }
    }
    ASSERT(!m_scriptNestingLevel);
}
void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
{
    ASSERT(pendingScript.watchingForLoad());
    m_host->stopWatchingForLoad(pendingScript.cachedScript());
    pendingScript.setWatchingForLoad(false);
}
void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript)
{
    ASSERT(!pendingScript.watchingForLoad());
    m_host->watchForLoad(pendingScript.cachedScript());
    pendingScript.setWatchingForLoad(true);
}
Exemple #25
0
void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
{
    ASSERT(pendingScript.watchingForLoad());
    m_host.stopWatchingForLoad(pendingScript);
}
void HTMLDocumentParser::stopWatchingForLoad(PendingScript& pendingScript)
{
    pendingScript.clearClient();
}