void XMLDocumentParser::parseEndElement() { exitText(); RefPtr<ContainerNode> n = m_currentNode; n->finishParsingChildren(); if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode() && toScriptElementIfPossible(toElement(n.get()))) { popCurrentNode(); n->remove(IGNORE_EXCEPTION); return; } if (!n->isElementNode() || !m_view) { if (!m_currentNodeStack.isEmpty()) popCurrentNode(); return; } Element* element = toElement(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 = toScriptElementIfPossible(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(); }
JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue initiator) { auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject); auto deferred = DeferredPromise::create(globalObject, jsPromise); if (moduleKeyValue.isSymbol()) { deferred->reject(TypeError, ASCIILiteral("Symbol module key should be already fulfilled with the inlined resource.")); return jsPromise.promise(); } if (!moduleKeyValue.isString()) { deferred->reject(TypeError, ASCIILiteral("Module key is not Symbol or String.")); return jsPromise.promise(); } // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script URL completedURL(URL(), asString(moduleKeyValue)->value(exec)); if (!completedURL.isValid()) { deferred->reject(TypeError, ASCIILiteral("Module key is a valid URL.")); return jsPromise.promise(); } ASSERT_WITH_MESSAGE(JSC::jsDynamicCast<JSElement*>(initiator), "Initiator should be an JSElement"); auto* scriptElement = toScriptElementIfPossible(&JSC::jsCast<JSElement*>(initiator)->wrapped()); ASSERT_WITH_MESSAGE(scriptElement, "Initiator should be ScriptElement."); if (auto* frame = m_document.frame()) { auto loader = CachedModuleScriptLoader::create(*this, deferred.get()); m_loaders.add(loader.copyRef()); if (!loader->load(*scriptElement, completedURL)) { loader->clearClient(); m_loaders.remove(WTFMove(loader)); deferred->reject(frame->script().moduleLoaderAlreadyReportedErrorSymbol()); return jsPromise.promise(); } } return jsPromise.promise(); }
void ScriptRunner::timerFired() { Ref<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(); toScriptElementIfPossible(element.get())->execute(cachedScript); m_document.decrementLoadEventDelayCount(); } }
void XMLDocumentParser::parseStartElement() { if (!m_sawFirstElement && m_parsingFragment) { // skip dummy element for fragments m_sawFirstElement = true; return; } exitText(); String localName = m_stream.name(); String uri = m_stream.namespaceUri(); String prefix = prefixFromQName(m_stream.qualifiedName().toString()); if (m_parsingFragment && uri.isNull()) { Q_ASSERT(prefix.isNull()); uri = m_defaultNamespaceURI; } QualifiedName qName(prefix, localName, uri); RefPtr<Element> newElement = document()->createElement(qName, true); if (!newElement) { stopParsing(); return; } bool isFirstElement = !m_sawFirstElement; m_sawFirstElement = true; Vector<Attribute> prefixedAttributes; ExceptionCode ec = 0; handleNamespaceAttributes(prefixedAttributes, m_stream.namespaceDeclarations(), ec); if (ec) { setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); stopParsing(); return; } handleElementAttributes(prefixedAttributes, m_stream.attributes(), ec); setAttributes(newElement.get(), prefixedAttributes, parserContentPolicy()); if (ec) { stopParsing(); return; } ScriptElement* scriptElement = toScriptElementIfPossible(newElement.get()); if (scriptElement) m_scriptStartPosition = textPosition(); m_currentNode->parserAppendChild(newElement.get()); pushCurrentNode(newElement.get()); if (m_view && !newElement->attached()) Style::attachRenderTree(newElement.get()); if (newElement->hasTagName(HTMLNames::htmlTag)) static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser(); if (isFirstElement && document()->frame()) document()->frame()->loader().dispatchDocumentElementAvailable(); }