// 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; }
// 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; }
// 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; }