void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) { ASSERT_UNUSED(unusedResource, unusedResource == m_pendingScript); ASSERT(m_pendingScript->accessCount() > 0); ScriptSourceCode sourceCode(m_pendingScript.get()); bool errorOccurred = m_pendingScript->errorOccurred(); bool wasCanceled = m_pendingScript->wasCanceled(); m_pendingScript->removeClient(this); m_pendingScript = 0; RefPtr<Element> e = m_scriptElement; m_scriptElement = 0; ScriptElement* scriptElement = toScriptElement(e.get()); ASSERT(scriptElement); // JavaScript can detach this parser, make sure it's kept alive even if detached. RefPtr<XMLDocumentParser> protect(this); if (errorOccurred) scriptElement->dispatchErrorEvent(); else if (!wasCanceled) { scriptElement->executeScript(sourceCode); scriptElement->dispatchLoadEvent(); } m_scriptElement = 0; if (!isDetached() && !m_requestingScript) resumeParsing(); }
void ScriptRunner::timerFired(Timer<ScriptRunner>* timer) { ActionLogScope log_scope("script runner timer"); ASSERT_UNUSED(timer, timer == &m_timer); RefPtr<Document> protect(m_document); Vector<PendingScript> scripts; scripts.swap(m_scriptsToExecuteSoon); size_t numInOrderScriptsToExecute = 0; for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_scriptsToExecuteInOrder[numInOrderScriptsToExecute].cachedScript()->isLoaded(); ++numInOrderScriptsToExecute) scripts.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecute]); if (numInOrderScriptsToExecute) m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute); size_t size = scripts.size(); for (size_t i = 0; i < size; ++i) { CachedScript* cachedScript = scripts[i].cachedScript(); RefPtr<Element> element = scripts[i].releaseElementAndClear(); ScriptElement* script = toScriptElement(element.get()); ActionLogFormat(ActionLog::READ_MEMORY, "ScriptRunner-%p-%p", static_cast<void*>(this), static_cast<void*>(script)); script->execute(cachedScript); m_document->decrementLoadEventDelayCount(); } }
void XMLTokenizer::notifyFinished(CachedResource* unusedResource) { ASSERT_UNUSED(unusedResource, unusedResource == m_pendingScript); ASSERT(m_pendingScript->accessCount() > 0); ScriptSourceCode sourceCode(m_pendingScript.get()); bool errorOccurred = m_pendingScript->errorOccurred(); m_pendingScript->removeClient(this); m_pendingScript = 0; RefPtr<Element> e = m_scriptElement; m_scriptElement = 0; ScriptElement* scriptElement = toScriptElement(e.get()); ASSERT(scriptElement); if (errorOccurred) scriptElement->dispatchErrorEvent(); else { m_view->frame()->loader()->executeScript(sourceCode); scriptElement->dispatchLoadEvent(); } m_scriptElement = 0; if (!m_requestingScript) resumeParsing(); }
// This method is meant to match the HTML5 definition of "running a script" // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script void HTMLScriptRunner::runScript(Element* script, const TextPosition1& scriptStartPosition) { ASSERT(m_document); ASSERT(!haveParsingBlockingScript()); { InsertionPointRecord insertionPointRecord(m_host->inputStream()); NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); ScriptElement* scriptElement = toScriptElement(script); ASSERT(scriptElement); if (!scriptElement->shouldExecuteAsJavaScript()) return; if (script->hasAttribute(srcAttr)) { if (script->hasAttribute(asyncAttr)) // Async takes precendence over defer. return; // Asynchronous scripts handle themselves. if (script->hasAttribute(deferAttr)) requestDeferredScript(script); else requestParsingBlockingScript(script); } else { // FIXME: We do not block inline <script> tags on stylesheets to match the // old parser for now. When we do, the ASSERT below should be added. // See https://bugs.webkit.org/show_bug.cgi?id=40047 // ASSERT(document()->haveStylesheetsLoaded()); ASSERT(isExecutingScript()); ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition); scriptElement->executeScript(sourceCode); } } }
void XMLTokenizer::endElementNs() { if (m_parserStopped) return; if (m_parserPaused) { m_pendingCallbacks->appendEndElementNSCallback(); return; } exitText(); Node* n = m_currentNode; RefPtr<Node> parent = n->parentNode(); n->finishParsingChildren(); if (!n->isElementNode() || !m_view) { setCurrentNode(parent.get()); return; } Element* element = static_cast<Element*>(n); ScriptElement* scriptElement = toScriptElement(element); if (!scriptElement) { setCurrentNode(parent.get()); return; } // don't load external scripts for standalone documents (for now) ASSERT(!m_pendingScript); m_requestingScript = true; String scriptHref = scriptElement->sourceAttributeValue(); if (!scriptHref.isEmpty()) { // we have a src attribute String scriptCharset = scriptElement->scriptCharset(); if ((m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, scriptCharset))) { m_scriptElement = element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and ref() executed it if (m_pendingScript) pauseParsing(); } else m_scriptElement = 0; } else m_view->frame()->loader()->executeScript(ScriptSourceCode(scriptElement->scriptContent(), m_doc->url(), m_scriptStartLine)); m_requestingScript = false; setCurrentNode(parent.get()); }
void XMLDocumentParser::parseEndElement() { exitText(); RefPtr<ContainerNode> n = m_currentNode; n->finishParsingChildren(); if (!scriptingContentIsAllowed(m_scriptingPermission) && n->isElementNode() && toScriptElement(static_cast<Element*>(n.get()))) { popCurrentNode(); ExceptionCode ec; n->remove(ec); return; } if (!n->isElementNode() || !m_view) { if (!m_currentNodeStack.isEmpty()) popCurrentNode(); return; } Element* element = static_cast<Element*>(n.get()); // The element's parent may have already been removed from document. // Parsing continues in this case, but scripts aren't executed. if (!element->inDocument()) { popCurrentNode(); return; } ScriptElement* scriptElement = toScriptElement(element); if (!scriptElement) { popCurrentNode(); return; } // don't load external scripts for standalone documents (for now) ASSERT(!m_pendingScript); m_requestingScript = true; if (scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) { if (scriptElement->readyToBeParserExecuted()) scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); else if (scriptElement->willBeParserExecuted()) { m_pendingScript = scriptElement->cachedScript(); m_scriptElement = element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and addClient() executed it. if (m_pendingScript) pauseParsing(); } else m_scriptElement = 0; } m_requestingScript = false; popCurrentNode(); }
// This method is meant to match the HTML5 definition of "running a script" // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script void HTMLScriptRunner::runScript(Element* script, const TextPosition1& scriptStartPosition) { ASSERT(m_document); ASSERT(!haveParsingBlockingScript()); { InsertionPointRecord insertionPointRecord(m_host->inputStream()); NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); ScriptElement* scriptElement = toScriptElement(script); ASSERT(scriptElement); scriptElement->prepareScript(scriptStartPosition); if (!scriptElement->willBeParserExecuted()) return; if (scriptElement->willExecuteWhenDocumentFinishedParsing()) requestDeferredScript(script); else if (scriptElement->readyToBeParserExecuted()) { if (m_scriptNestingLevel == 1) { m_parsingBlockingScript.setElement(script); m_parsingBlockingScript.setStartingPosition(scriptStartPosition); } else { ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition); scriptElement->executeScript(sourceCode); } } else requestParsingBlockingScript(script); } }
void XMLDocumentParser::notifyFinished(CachedResource* unusedResource) { ASSERT_UNUSED(unusedResource, unusedResource == m_pendingScript); #if PLATFORM(OLYMPIA) Settings* settings = document() ? document()->settings() : 0; ASSERT(m_pendingScript->accessCount() > 0 || cache()->disabled() || !settings || !settings->useCache()); #else ASSERT(m_pendingScript->accessCount() > 0); #endif ScriptSourceCode sourceCode(m_pendingScript.get()); bool errorOccurred = m_pendingScript->errorOccurred(); m_pendingScript->removeClient(this); m_pendingScript = 0; RefPtr<Element> e = m_scriptElement; m_scriptElement = 0; ScriptElement* scriptElement = toScriptElement(e.get()); ASSERT(scriptElement); // JavaScript can detach this parser, make sure it's kept alive even if detached. RefPtr<XMLDocumentParser> protect(this); if (errorOccurred) scriptElement->dispatchErrorEvent(); else { m_view->frame()->script()->executeScript(sourceCode); scriptElement->dispatchLoadEvent(); } m_scriptElement = 0; if (!isDetached() && !m_requestingScript) resumeParsing(); }
void ScriptRunner::queueScriptForExecution(ScriptElement& scriptElement, LoadableScript& loadableScript, ExecutionType executionType) { ASSERT(scriptElement.element().inDocument()); m_document.incrementLoadEventDelayCount(); auto pendingScript = PendingScript::create(scriptElement, loadableScript); switch (executionType) { case ASYNC_EXECUTION: m_pendingAsyncScripts.add(pendingScript.copyRef()); break; case IN_ORDER_EXECUTION: m_scriptsToExecuteInOrder.append(pendingScript.copyRef()); break; } pendingScript->setClient(*this); }
// This method is meant to match the HTML5 definition of "running a script" // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStartPosition) { ASSERT(m_document); ASSERT(!hasParserBlockingScript()); { ScriptElement* scriptElement = toScriptElement(script); // This contains both and ASSERTION and a null check since we should not // be getting into the case of a null script element, but seem to be from // time to time. The assertion is left in to help find those cases and // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. ASSERT(scriptElement); if (!scriptElement) return; // FIXME: This may be too agressive as we always deliver mutations at // every script element, even if it's not ready to execute yet. There's // unfortuantely no obvious way to tell if prepareScript is going to // execute the script from out here. if (!isExecutingScript()) { #if ENABLE(CUSTOM_ELEMENTS) CustomElementRegistry::deliverAllLifecycleCallbacks(); #endif MutationObserver::deliverAllMutations(); } InsertionPointRecord insertionPointRecord(m_host->inputStream()); NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); scriptElement->prepareScript(scriptStartPosition); if (!scriptElement->willBeParserExecuted()) return; if (scriptElement->willExecuteWhenDocumentFinishedParsing()) requestDeferredScript(script); else if (scriptElement->readyToBeParserExecuted()) { if (m_scriptNestingLevel == 1) { m_parserBlockingScript.setElement(script); m_parserBlockingScript.setStartingPosition(scriptStartPosition); } else { ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition); scriptElement->executeScript(sourceCode); } } else requestParsingBlockingScript(script); } }
// This method is meant to match the HTML5 definition of "running a script" // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStartPosition) { ASSERT(m_document); ASSERT(!hasParserBlockingScript()); { ScriptElement* scriptElement = toScriptElementIfPossible(script); // This contains both and ASSERTION and a null check since we should not // be getting into the case of a null script element, but seem to be from // time to time. The assertion is left in to help find those cases and // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. ASSERT(scriptElement); if (!scriptElement) return; // FIXME: This may be too agressive as we always deliver mutations at // every script element, even if it's not ready to execute yet. There's // unfortuantely no obvious way to tell if prepareScript is going to // execute the script from out here. if (!isExecutingScript()) MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint(); InsertionPointRecord insertionPointRecord(m_host.inputStream()); NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); scriptElement->prepareScript(scriptStartPosition); if (!scriptElement->willBeParserExecuted()) return; if (scriptElement->willExecuteWhenDocumentFinishedParsing()) requestDeferredScript(script); else if (scriptElement->readyToBeParserExecuted()) { if (m_scriptNestingLevel == 1) m_parserBlockingScript = PendingScript::create(*script, scriptStartPosition); else scriptElement->executeClassicScript(ScriptSourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition)); } else requestParsingBlockingScript(script); } }
// This method is meant to match the HTML5 definition of "running a script" // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script void HTMLScriptRunner::runScript(Element* script, const TextPosition1& scriptStartPosition) { ASSERT(m_document); ASSERT(!haveParsingBlockingScript()); { InsertionPointRecord insertionPointRecord(m_host->inputStream()); NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); ScriptElement* scriptElement = toScriptElement(script); // This contains both and ASSERTION and a null check since we should not // be getting into the case of a null script element, but seem to be from // time to time. The assertion is left in to help find those cases and // is being tracked by <https://bugs.webkit.org/show_bug.cgi?id=60559>. ASSERT(scriptElement); if (!scriptElement) return; scriptElement->prepareScript(scriptStartPosition); if (!scriptElement->willBeParserExecuted()) return; if (scriptElement->willExecuteWhenDocumentFinishedParsing()) requestDeferredScript(script); else if (scriptElement->readyToBeParserExecuted()) { if (m_scriptNestingLevel == 1) { m_parsingBlockingScript.setElement(script); m_parsingBlockingScript.setStartingPosition(scriptStartPosition); } else { ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition); scriptElement->executeScript(sourceCode); } } else requestParsingBlockingScript(script); } }
void XMLTokenizer::endElementNs() { if (m_parserStopped) return; if (m_parserPaused) { m_pendingCallbacks->appendEndElementNSCallback(); return; } exitText(); Node* n = m_currentNode; n->finishParsingChildren(); if (m_scriptingPermission == FragmentScriptingNotAllowed && n->isElementNode() && toScriptElement(static_cast<Element*>(n))) { popCurrentNode(); ExceptionCode ec; n->remove(ec); return; } if (!n->isElementNode() || !m_view) { popCurrentNode(); return; } Element* element = static_cast<Element*>(n); // The element's parent may have already been removed from document. // Parsing continues in this case, but scripts aren't executed. if (!element->inDocument()) { popCurrentNode(); return; } ScriptElement* scriptElement = toScriptElement(element); if (!scriptElement) { popCurrentNode(); return; } // Don't load external scripts for standalone documents (for now). ASSERT(!m_pendingScript); m_requestingScript = true; #if ENABLE(XHTMLMP) if (!scriptElement->shouldExecuteAsJavaScript()) m_doc->setShouldProcessNoscriptElement(true); else #endif { String scriptHref = scriptElement->sourceAttributeValue(); if (!scriptHref.isEmpty()) { // we have a src attribute String scriptCharset = scriptElement->scriptCharset(); if (element->dispatchBeforeLoadEvent(scriptHref) && (m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, scriptCharset))) { m_scriptElement = element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and ref() executed it if (m_pendingScript) pauseParsing(); } else m_scriptElement = 0; } else m_view->frame()->script()->executeScript(ScriptSourceCode(scriptElement->scriptContent(), m_doc->url(), m_scriptStartLine)); } m_requestingScript = false; popCurrentNode(); }
void XMLDocumentParser::endElementNs() { if (isStopped()) return; if (m_parserPaused) { m_pendingCallbacks->appendEndElementNSCallback(); return; } // JavaScript can detach the parser. Make sure this is not released // before the end of this method. RefPtr<XMLDocumentParser> protect(this); exitText(); RefPtr<ContainerNode> n = m_currentNode; n->finishParsingChildren(); if (m_scriptingPermission == FragmentScriptingNotAllowed && n->isElementNode() && toScriptElement(static_cast<Element*>(n.get()))) { popCurrentNode(); ExceptionCode ec; n->remove(ec); return; } if (!n->isElementNode() || !m_view) { popCurrentNode(); return; } Element* element = static_cast<Element*>(n.get()); // The element's parent may have already been removed from document. // Parsing continues in this case, but scripts aren't executed. if (!element->inDocument()) { popCurrentNode(); return; } ScriptElement* scriptElement = toScriptElement(element); if (!scriptElement) { popCurrentNode(); return; } // Don't load external scripts for standalone documents (for now). ASSERT(!m_pendingScript); m_requestingScript = true; if (scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) { // FIXME: Script execution should be shared between // the libxml2 and Qt XMLDocumentParser implementations. if (scriptElement->readyToBeParserExecuted()) scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); else if (scriptElement->willBeParserExecuted()) { m_pendingScript = scriptElement->cachedScript(); m_scriptElement = element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and addClient() executed it. if (m_pendingScript) pauseParsing(); } else m_scriptElement = 0; // JavaScript may have detached the parser if (isDetached()) return; } m_requestingScript = false; popCurrentNode(); }
void HTMLScriptRunner::executeScript(Element* element, const ScriptSourceCode& sourceCode) const { ASSERT(m_document); ScriptElement* scriptElement = toScriptElement(element); ASSERT(scriptElement); if (!scriptElement->shouldExecuteAsJavaScript()) return; ASSERT(isExecutingScript()); if (!m_document->frame()) return; String shouldExecuteInIsolatedWorld = element->getAttribute("worldID"); String sharedLibraryId = element->getAttribute("SharedLibId"); String UseLibId = element->getAttribute("UseLibId"); bool writable = true; if (((Node *)element)->parentElement()) { String ACL=((Node *)element)->parentElement()->getAttribute("ACL"); String ROACL=((Node *)element)->parentElement()->getAttribute("ROACL"); int worldID = shouldExecuteInIsolatedWorld.toInt(); bool flag = false; bool flag2 = false; if (worldID != 0) { if ((ROACL != NULL)&&(ROACL != "")) { Vector<WTF::String> ACLs; ROACL.split(";",ACLs); for (unsigned int i=0; i<ACLs.size(); i++) { if (worldID==ACLs[i].toInt()) { ACLs.clear(); flag = true; } } ACLs.clear(); } if (flag == true) { if ((ACL != NULL)&&(ACL != "")) { Vector<WTF::String> ACLs; ACL.split(";",ACLs); for (unsigned int i=0; i<ACLs.size(); i++) { if (worldID==ACLs[i].toInt()) { ACLs.clear(); flag2 = true; } } ACLs.clear(); } } writable = flag && flag2; } } if (!shouldExecuteInIsolatedWorld) shouldExecuteInIsolatedWorld=""; if (!sharedLibraryId) sharedLibraryId=""; if (!UseLibId) UseLibId=""; m_document->frame()->script()->executeScript(sourceCode, (ShouldAllowXSS) false, shouldExecuteInIsolatedWorld, sharedLibraryId, UseLibId, writable); }
void XMLDocumentParser::endElementNs() { if (isStopped()) return; if (m_parserPaused) { m_pendingCallbacks->appendEndElementNSCallback(); return; } exitText(); Node* n = m_currentNode; n->finishParsingChildren(); if (m_scriptingPermission == FragmentScriptingNotAllowed && n->isElementNode() && toScriptElement(static_cast<Element*>(n))) { popCurrentNode(); ExceptionCode ec; n->remove(ec); return; } if (!n->isElementNode() || !m_view) { popCurrentNode(); return; } Element* element = static_cast<Element*>(n); // The element's parent may have already been removed from document. // Parsing continues in this case, but scripts aren't executed. if (!element->inDocument()) { popCurrentNode(); return; } ScriptElement* scriptElement = toScriptElement(element); if (!scriptElement) { popCurrentNode(); return; } // Don't load external scripts for standalone documents (for now). ASSERT(!m_pendingScript); m_requestingScript = true; #if ENABLE(XHTMLMP) if (!scriptElement->shouldExecuteAsJavaScript()) document()->setShouldProcessNoscriptElement(true); else #endif { // FIXME: Script execution should be shared should be shared between // the libxml2 and Qt XMLDocumentParser implementations. // JavaScript can detach the parser. Make sure this is not released // before the end of this method. RefPtr<XMLDocumentParser> protect(this); String scriptHref = scriptElement->sourceAttributeValue(); if (!scriptHref.isEmpty()) { // we have a src attribute String scriptCharset = scriptElement->scriptCharset(); if (element->dispatchBeforeLoadEvent(scriptHref) && (m_pendingScript = document()->cachedResourceLoader()->requestScript(scriptHref, scriptCharset))) { m_scriptElement = element; m_pendingScript->addClient(this); // m_pendingScript will be 0 if script was already loaded and ref() executed it if (m_pendingScript) pauseParsing(); } else m_scriptElement = 0; } else scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition)); // JavaScript may have detached the parser if (isDetached()) return; } m_requestingScript = false; popCurrentNode(); }