Changeset 223999 in webkit


Ignore:
Timestamp:
Oct 25, 2017 5:30:03 PM (6 years ago)
Author:
rniwa@webkit.org
Message:

Style::Scope::flushPendingUpdate() can replace the entire document in XSLTProcessor::createDocumentFromSource
https://bugs.webkit.org/show_bug.cgi?id=178715
<rdar://problem/35144665>

Reviewed by Brent Fulgham.

Apply XLS tranforms when a 0s timer fires or the document finishes parsing or loading whichever comes first
instead of in the middle of collecting a list of stylesheets.

  • dom/Document.cpp:

(WebCore::Document::Document): Initialize the newly added timer.
(WebCore::Document::implicitClose): Apply any pending XSLT before we fire load events since some of the event
handlers may be expecting to see the document after XSLT had been applied.
(WebCore::Document::scheduleToApplyXSLTransforms): Added.
(WebCore::Document::applyPendingXSLTransformsNowIfScheduled): Added.
(WebCore::Document::applyPendingXSLTransformsTimerFired): Added. Moved the logic to apply XSL transforms from
Style::Scope::collectActiveStyleSheets, and merged applyXSLTransform into this function.
(WebCore::Document::applyXSLTransform): Deleted.
(WebCore::Document::finishedParsing): Apply XSLT right before updating the style. This is where used to apply
inline XSLT and it happens much earlier than implicitClose.

  • dom/Document.h:
  • dom/ProcessingInstruction.cpp:

(WebCore::ProcessingInstruction::checkStyleSheet): Schedule XSLT in the document instead of flushing pending
stylesheets, which would have synchronously applied XSLT. We can't apply XSLT synchronously here because this
function can be called from a non-script-resilient call stack.
(WebCore::ProcessingInstruction::sheetLoaded): Ditto.

  • style/StyleScope.cpp:

(WebCore::Style::Scope::collectXSLTransforms): Added.
(WebCore::Style::Scope::collectActiveStyleSheets): Removed the code to apply XSLT. Skip ProcessingInstructions
that applies XSLT. Also use RefPtr<StyleSheet> instead of a raw pointer to store StyleSheet.

  • style/StyleScope.h:
  • xml/parser/XMLDocumentParserLibxml2.cpp:

(WebCore::XMLDocumentParser::doEnd): Apply any pending XSLTs synchronously here as the comment suggests.

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r223998 r223999  
     12017-10-25  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Style::Scope::flushPendingUpdate() can replace the entire document in XSLTProcessor::createDocumentFromSource
     4        https://bugs.webkit.org/show_bug.cgi?id=178715
     5        <rdar://problem/35144665>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Apply XLS tranforms when a 0s timer fires or the document finishes parsing or loading whichever comes first
     10        instead of in the middle of collecting a list of stylesheets.
     11
     12        * dom/Document.cpp:
     13        (WebCore::Document::Document): Initialize the newly added timer.
     14        (WebCore::Document::implicitClose): Apply any pending XSLT before we fire load events since some of the event
     15        handlers may be expecting to see the document after XSLT had been applied.
     16        (WebCore::Document::scheduleToApplyXSLTransforms): Added.
     17        (WebCore::Document::applyPendingXSLTransformsNowIfScheduled): Added.
     18        (WebCore::Document::applyPendingXSLTransformsTimerFired): Added. Moved the logic to apply XSL transforms from
     19        Style::Scope::collectActiveStyleSheets, and merged applyXSLTransform into this function.
     20        (WebCore::Document::applyXSLTransform): Deleted.
     21        (WebCore::Document::finishedParsing): Apply XSLT right before updating the style. This is where used to apply
     22        inline XSLT and it happens much earlier than implicitClose.
     23        * dom/Document.h:
     24        * dom/ProcessingInstruction.cpp:
     25        (WebCore::ProcessingInstruction::checkStyleSheet): Schedule XSLT in the document instead of flushing pending
     26        stylesheets, which would have synchronously applied XSLT. We can't apply XSLT synchronously here because this
     27        function can be called from a non-script-resilient call stack.
     28        (WebCore::ProcessingInstruction::sheetLoaded): Ditto.
     29        * style/StyleScope.cpp:
     30        (WebCore::Style::Scope::collectXSLTransforms): Added.
     31        (WebCore::Style::Scope::collectActiveStyleSheets): Removed the code to apply XSLT. Skip ProcessingInstructions
     32        that applies XSLT. Also use RefPtr<StyleSheet> instead of a raw pointer to store StyleSheet.
     33        * style/StyleScope.h:
     34        * xml/parser/XMLDocumentParserLibxml2.cpp:
     35        (WebCore::XMLDocumentParser::doEnd): Apply any pending XSLTs synchronously here as the comment suggests.
     36
    1372017-10-25  Devin Rousso  <webkit@devinrousso.com>
    238
  • trunk/Source/WebCore/dom/Document.cpp

    r223929 r223999  
    470470    , m_scriptRunner(std::make_unique<ScriptRunner>(*this))
    471471    , m_moduleLoader(std::make_unique<ScriptModuleLoader>(*this))
     472    , m_applyPendingXSLTransformsTimer(*this, &Document::applyPendingXSLTransformsTimerFired)
    472473    , m_xmlVersion(ASCIILiteral("1.0"))
    473474    , m_constantPropertyMap(std::make_unique<ConstantPropertyMap>(*this))
     
    27262727    RefPtr<Frame> f = frame();
    27272728    if (f) {
     2729        // Apply XSL transforms before load events so that event handlers can access the transformed DOM tree.
     2730        applyPendingXSLTransformsNowIfScheduled();
     2731
    27282732        if (auto* documentLoader = loader())
    27292733            documentLoader->startIconLoading();
     
    50515055#if ENABLE(XSLT)
    50525056
    5053 void Document::applyXSLTransform(ProcessingInstruction* pi)
    5054 {
    5055     RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
    5056     processor->setXSLStyleSheet(downcast<XSLStyleSheet>(pi->sheet()));
    5057     String resultMIMEType;
    5058     String newSource;
    5059     String resultEncoding;
    5060     if (!processor->transformToString(*this, resultMIMEType, newSource, resultEncoding))
    5061         return;
    5062     // FIXME: If the transform failed we should probably report an error (like Mozilla does).
    5063     Frame* ownerFrame = frame();
    5064     processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, ownerFrame);
     5057void Document::scheduleToApplyXSLTransforms()
     5058{
     5059    if (!m_applyPendingXSLTransformsTimer.isActive())
     5060        m_applyPendingXSLTransformsTimer.startOneShot(0_s);
     5061}
     5062
     5063void Document::applyPendingXSLTransformsNowIfScheduled()
     5064{
     5065    if (!m_applyPendingXSLTransformsTimer.isActive())
     5066        return;
     5067    m_applyPendingXSLTransformsTimer.stop();
     5068    applyPendingXSLTransformsTimerFired();
     5069}
     5070
     5071void Document::applyPendingXSLTransformsTimerFired()
     5072{
     5073    if (parsing())
     5074        return;
     5075
     5076    ASSERT(NoEventDispatchAssertion::isEventAllowedInMainThread());
     5077    for (auto& processingInstruction : styleScope().collectXSLTransforms()) {
     5078        ASSERT(processingInstruction->isXSL());
     5079
     5080        // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
     5081        if (transformSourceDocument() || !processingInstruction->sheet())
     5082            return;
     5083
     5084        auto processor = XSLTProcessor::create();
     5085        processor->setXSLStyleSheet(downcast<XSLStyleSheet>(processingInstruction->sheet()));
     5086        String resultMIMEType;
     5087        String newSource;
     5088        String resultEncoding;
     5089        if (!processor->transformToString(*this, resultMIMEType, newSource, resultEncoding))
     5090            continue;
     5091        // FIXME: If the transform failed we should probably report an error (like Mozilla does).
     5092        processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame());
     5093    }
    50655094}
    50665095
     
    52445273    setParsing(false);
    52455274
     5275    Ref<Document> protectedThis(*this);
     5276
    52465277    if (!m_documentTiming.domContentLoadedEventStart)
    52475278        m_documentTiming.domContentLoadedEventStart = MonotonicTime::now();
     
    52535284
    52545285    if (RefPtr<Frame> frame = this->frame()) {
     5286        applyPendingXSLTransformsNowIfScheduled();
     5287
    52555288        // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
    52565289        // resource loads are complete. HTMLObjectElements can start loading their resources from
  • trunk/Source/WebCore/dom/Document.h

    r223929 r223999  
    945945
    946946#if ENABLE(XSLT)
    947     void applyXSLTransform(ProcessingInstruction* pi);
     947    void scheduleToApplyXSLTransforms();
     948    void applyPendingXSLTransformsNowIfScheduled();
    948949    RefPtr<Document> transformSourceDocument() { return m_transformSourceDocument; }
    949950    void setTransformSourceDocument(Document* doc) { m_transformSourceDocument = doc; }
     
    15591560
    15601561#if ENABLE(XSLT)
     1562    void applyPendingXSLTransformsTimerFired();
     1563
    15611564    std::unique_ptr<TransformSource> m_transformSource;
    15621565    RefPtr<Document> m_transformSourceDocument;
     1566    Timer m_applyPendingXSLTransformsTimer;
    15631567#endif
    15641568
  • trunk/Source/WebCore/dom/ProcessingInstruction.cpp

    r223802 r223999  
    127127                m_sheet = XSLStyleSheet::createEmbedded(this, finalURL);
    128128                m_loading = false;
     129                document().scheduleToApplyXSLTransforms();
    129130            }
    130131#endif
     
    180181#if ENABLE(XSLT)
    181182                if (m_isXSL)
    182                     document().styleScope().flushPendingUpdate();
     183                    document().scheduleToApplyXSLTransforms();
    183184#endif
    184185            }
     
    203204#if ENABLE(XSLT)
    204205        if (m_isXSL)
    205             document().styleScope().flushPendingUpdate();
     206            document().scheduleToApplyXSLTransforms();
    206207#endif
    207208        return true;
  • trunk/Source/WebCore/style/StyleScope.cpp

    r223047 r223999  
    291291}
    292292
     293#if ENABLE(XSLT)
     294// FIXME: <https://webkit.org/b/178830> Remove XSLT relaed code from Style::Scope.
     295Vector<Ref<ProcessingInstruction>> Scope::collectXSLTransforms()
     296{
     297    Vector<Ref<ProcessingInstruction>> processingInstructions;
     298    for (auto& node : m_styleSheetCandidateNodes) {
     299        if (is<ProcessingInstruction>(*node) && downcast<ProcessingInstruction>(*node).isXSL())
     300            processingInstructions.append(downcast<ProcessingInstruction>(*node));
     301    }
     302    return processingInstructions;
     303}
     304#endif
     305
    293306void Scope::collectActiveStyleSheets(Vector<RefPtr<StyleSheet>>& sheets)
    294307{
     
    297310
    298311    for (auto& node : m_styleSheetCandidateNodes) {
    299         StyleSheet* sheet = nullptr;
     312        RefPtr<StyleSheet> sheet;
    300313        if (is<ProcessingInstruction>(*node)) {
    301             // Processing instruction (XML documents only).
     314            if (!downcast<ProcessingInstruction>(*node).isCSS())
     315                continue;
    302316            // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
    303             ProcessingInstruction& pi = downcast<ProcessingInstruction>(*node);
    304             sheet = pi.sheet();
    305 #if ENABLE(XSLT)
    306             // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
    307             if (pi.isXSL() && !m_document.transformSourceDocument()) {
    308                 // Don't apply XSL transforms until loading is finished.
    309                 if (!m_document.parsing())
    310                     m_document.applyXSLTransform(&pi);
    311                 return;
    312             }
    313 #endif
     317            sheet = downcast<ProcessingInstruction>(*node).sheet();
    314318        } else if (is<HTMLLinkElement>(*node) || is<HTMLStyleElement>(*node) || is<SVGStyleElement>(*node)) {
    315319            Element& element = downcast<Element>(*node);
     
    365369        }
    366370        if (sheet)
    367             sheets.append(sheet);
     371            sheets.append(WTFMove(sheet));
    368372    }
    369373}
  • trunk/Source/WebCore/style/StyleScope.h

    r218793 r223999  
    109109    void flushPendingUpdate();
    110110
     111#if ENABLE(XSLT)
     112    Vector<Ref<ProcessingInstruction>> collectXSLTransforms();
     113#endif
     114
    111115    StyleResolver& resolver();
    112116    StyleResolver* resolverIfExists();
  • trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp

    r223728 r223999  
    13341334
    13351335        document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets.
    1336         document()->styleScope().didChangeActiveStyleSheetCandidates();
     1336        document()->applyPendingXSLTransformsNowIfScheduled();
    13371337
    13381338        // styleResolverChanged() call can detach the parser and null out its document.
Note: See TracChangeset for help on using the changeset viewer.