| Differences between
and this patch
- a/Source/WebCore/ChangeLog +56 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2019-08-13  Rob Buis  <rbuis@igalia.com>
2
3
        Support lazy image and iframe loading (loading="lazy")
4
        https://bugs.webkit.org/show_bug.cgi?id=196698
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Implement lazy image loading as specified here [1]. Lazy image loading
9
        is controlled by the loading attribute and automatic for CSS
10
        background images. When the loading attribute is auto or not
11
        specified, the behavior is like before this patch, i.e. loading is
12
        eager.
13
14
        [1] https://github.com/whatwg/html/pull/3752/files
15
16
        * Sources.txt:
17
        * WebCore.xcodeproj/project.pbxproj:
18
        * css/parser/CSSParser.cpp:
19
        (WebCore::CSSParser::parseInlineStyleDeclaration):
20
        * css/parser/CSSParser.h:
21
        * css/parser/CSSParserImpl.cpp:
22
        (WebCore::CSSParserImpl::parseInlineStyleDeclaration):
23
        * css/parser/CSSParserImpl.h:
24
        * dom/Document.cpp:
25
        (WebCore::Document::ensureLazyLoadImageObserver):
26
        * dom/Document.h:
27
        * html/HTMLImageElement.cpp:
28
        (WebCore::HTMLImageElement::HTMLImageElement):
29
        (WebCore::HTMLImageElement::create):
30
        (WebCore::HTMLImageElement::parseAttribute):
31
        (WebCore::HTMLImageElement::loadDeferredImage):
32
        (WebCore::HTMLImageElement::getAttributeLazyLoadDimensionType):
33
        (WebCore::HTMLImageElement::getInlineStyleDimensionsType):
34
        * html/HTMLImageElement.h:
35
        (WebCore::HTMLImageElement::createdByParser const):
36
        * html/HTMLTagNames.in:
37
        * html/LazyLoadImageObserver.cpp: Added.
38
        (WebCore::LazyLoadImageObserver::startMonitoring):
39
        (WebCore::LazyLoadImageObserver::stopMonitoring):
40
        (WebCore::LazyLoadImageObserver::startMonitoringNearViewport):
41
        * html/LazyLoadImageObserver.h: Added.
42
        * html/parser/HTMLPreloadScanner.cpp:
43
        (WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest):
44
        (WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
45
        * html/parser/HTMLPreloadScanner.h:
46
        * loader/ImageLoader.cpp:
47
        (WebCore::isLazyLoadableImage):
48
        (WebCore::isDimensionAbsoluteLarge):
49
        (WebCore::ImageLoader::updateFromElement):
50
        (WebCore::ImageLoader::notifyFinished):
51
        (WebCore::ImageLoader::loadDeferredImage):
52
        * loader/ImageLoader.h:
53
        * loader/cache/CachedResourceLoader.cpp:
54
        (WebCore::CachedResourceLoader::requestImage):
55
        * loader/cache/CachedResourceLoader.h:
56
1
2019-08-12  Ryosuke Niwa  <rniwa@webkit.org>
57
2019-08-12  Ryosuke Niwa  <rniwa@webkit.org>
2
58
3
        FrameLoader::open can execute scritps via style recalc in Frame::setDocument
59
        FrameLoader::open can execute scritps via style recalc in Frame::setDocument
- a/Source/WebCore/Sources.txt +1 lines
Lines 1196-1201 html/InputType.cpp a/Source/WebCore/Sources.txt_sec1
1196
html/InputTypeNames.cpp
1196
html/InputTypeNames.cpp
1197
html/LabelableElement.cpp
1197
html/LabelableElement.cpp
1198
html/LabelsNodeList.cpp
1198
html/LabelsNodeList.cpp
1199
html/LazyLoadImageObserver.cpp
1199
html/LinkIconCollector.cpp
1200
html/LinkIconCollector.cpp
1200
html/LinkRelAttribute.cpp
1201
html/LinkRelAttribute.cpp
1201
html/MediaController.cpp
1202
html/MediaController.cpp
- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj -2 / +9 lines
Lines 3336-3341 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
3336
		AA7FEEAD16A4E74B004C0C33 /* JSSpeechSynthesis.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7FEEAC16A4E74B004C0C33 /* JSSpeechSynthesis.h */; };
3336
		AA7FEEAD16A4E74B004C0C33 /* JSSpeechSynthesis.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7FEEAC16A4E74B004C0C33 /* JSSpeechSynthesis.h */; };
3337
		AAA728F716D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = AAA728F116D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h */; };
3337
		AAA728F716D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = AAA728F116D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h */; };
3338
		AAC08CF315F941FD00F1E188 /* AccessibilitySVGRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */; };
3338
		AAC08CF315F941FD00F1E188 /* AccessibilitySVGRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */; };
3339
        AAD9D0B521DFA810001B11C7 /* LazyLoadImageObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
3339
		AB23A32809BBA7D00067CC53 /* BeforeTextInsertedEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = AB23A32609BBA7D00067CC53 /* BeforeTextInsertedEvent.h */; };
3340
		AB23A32809BBA7D00067CC53 /* BeforeTextInsertedEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = AB23A32609BBA7D00067CC53 /* BeforeTextInsertedEvent.h */; };
3340
		AB247A6D0AFD6383003FA5FD /* RenderSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = AB247A6B0AFD6383003FA5FD /* RenderSlider.h */; };
3341
		AB247A6D0AFD6383003FA5FD /* RenderSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = AB247A6B0AFD6383003FA5FD /* RenderSlider.h */; };
3341
		AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AB31C91D10AE1B8E000C7B92 /* LineClampValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
3342
		AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AB31C91D10AE1B8E000C7B92 /* LineClampValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 11987-11992 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
11987
		AAA728F316D1D8BC00D3BBC6 /* AXObjectCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AXObjectCacheIOS.mm; sourceTree = "<group>"; };
11988
		AAA728F316D1D8BC00D3BBC6 /* AXObjectCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AXObjectCacheIOS.mm; sourceTree = "<group>"; };
11988
		AAC08CF015F941FC00F1E188 /* AccessibilitySVGRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilitySVGRoot.cpp; sourceTree = "<group>"; };
11989
		AAC08CF015F941FC00F1E188 /* AccessibilitySVGRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilitySVGRoot.cpp; sourceTree = "<group>"; };
11989
		AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySVGRoot.h; sourceTree = "<group>"; };
11990
		AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySVGRoot.h; sourceTree = "<group>"; };
11991
		AAD9D0B121DFA80C001B11C7 /* LazyLoadImageObserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyLoadImageObserver.cpp; sourceTree = "<group>"; };
11992
		AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyLoadImageObserver.h; sourceTree = "<group>"; };
11993
11990
		AAE27B7416CBFC0D00623043 /* PlatformSpeechSynthesizerMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformSpeechSynthesizerMock.cpp; sourceTree = "<group>"; };
11994
		AAE27B7416CBFC0D00623043 /* PlatformSpeechSynthesizerMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformSpeechSynthesizerMock.cpp; sourceTree = "<group>"; };
11991
		AAE27B7516CBFC0D00623043 /* PlatformSpeechSynthesizerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizerMock.h; sourceTree = "<group>"; };
11995
		AAE27B7516CBFC0D00623043 /* PlatformSpeechSynthesizerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizerMock.h; sourceTree = "<group>"; };
11992
		AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerIOS.mm; sourceTree = "<group>"; };
11996
		AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerIOS.mm; sourceTree = "<group>"; };
Lines 17084-17091 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
17084
				C21BF72021CD89DD00227979 /* WHLSLEnumerationDefinition.h */,
17088
				C21BF72021CD89DD00227979 /* WHLSLEnumerationDefinition.h */,
17085
				C21BF72621CD89E300227979 /* WHLSLEnumerationMember.h */,
17089
				C21BF72621CD89E300227979 /* WHLSLEnumerationMember.h */,
17086
				C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */,
17090
				C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */,
17087
				C21BF70C21CD89CC00227979 /* WHLSLExpression.h */,
17088
				522D07A322FBAB4300B905BE /* WHLSLExpression.cpp */,
17091
				522D07A322FBAB4300B905BE /* WHLSLExpression.cpp */,
17092
				C21BF70C21CD89CC00227979 /* WHLSLExpression.h */,
17089
				C21BF70021CD89C200227979 /* WHLSLFallthrough.h */,
17093
				C21BF70021CD89C200227979 /* WHLSLFallthrough.h */,
17090
				C21BF73521CD89F200227979 /* WHLSLFloatLiteral.h */,
17094
				C21BF73521CD89F200227979 /* WHLSLFloatLiteral.h */,
17091
				1CB69B3821DF03E1006E846A /* WHLSLFloatLiteralType.cpp */,
17095
				1CB69B3821DF03E1006E846A /* WHLSLFloatLiteralType.cpp */,
Lines 21630-21635 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
21630
				450CEBEF15073BBE002BB149 /* LabelableElement.h */,
21634
				450CEBEF15073BBE002BB149 /* LabelableElement.h */,
21631
				A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */,
21635
				A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */,
21632
				A456FA2511AD4A830020B420 /* LabelsNodeList.h */,
21636
				A456FA2511AD4A830020B420 /* LabelsNodeList.h */,
21637
				AAD9D0B121DFA80C001B11C7 /* LazyLoadImageObserver.cpp */,
21638
				AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */,
21633
				1A4DA41F1CDD3A8300F4473C /* LinkIconCollector.cpp */,
21639
				1A4DA41F1CDD3A8300F4473C /* LinkIconCollector.cpp */,
21634
				1A4DA4201CDD3A8300F4473C /* LinkIconCollector.h */,
21640
				1A4DA4201CDD3A8300F4473C /* LinkIconCollector.h */,
21635
				1A250E0C1CDD632000D0BE63 /* LinkIconType.h */,
21641
				1A250E0C1CDD632000D0BE63 /* LinkIconType.h */,
Lines 28601-28606 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec5
28601
				E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */,
28607
				E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */,
28602
				0F60F32B1DFBB10700416D6C /* CommonVM.h in Headers */,
28608
				0F60F32B1DFBB10700416D6C /* CommonVM.h in Headers */,
28603
				7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */,
28609
				7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */,
28610
				E4E94D6122FF158A00DD191F /* ComplexLineLayout.h in Headers */,
28604
				C2F4E78C1E45C3EF006D7105 /* ComplexTextController.h in Headers */,
28611
				C2F4E78C1E45C3EF006D7105 /* ComplexTextController.h in Headers */,
28605
				E4BA50901BCFBD9500E34EF7 /* ComposedTreeAncestorIterator.h in Headers */,
28612
				E4BA50901BCFBD9500E34EF7 /* ComposedTreeAncestorIterator.h in Headers */,
28606
				E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */,
28613
				E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */,
Lines 30563-30568 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec6
30563
				6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */,
30570
				6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */,
30564
				11310CF220BA4A320065A8D0 /* LayoutTreeBuilder.h in Headers */,
30571
				11310CF220BA4A320065A8D0 /* LayoutTreeBuilder.h in Headers */,
30565
				141DC0481648348F00371E5A /* LayoutUnit.h in Headers */,
30572
				141DC0481648348F00371E5A /* LayoutUnit.h in Headers */,
30573
                AAD9D0B521DFA810001B11C7 /* LazyLoadImageObserver.h in Headers */,
30566
				CDE8B5ED1A69777300B4B66A /* LegacyCDMPrivateClearKey.h in Headers */,
30574
				CDE8B5ED1A69777300B4B66A /* LegacyCDMPrivateClearKey.h in Headers */,
30567
				CDF4B7121E0087AE00E235A2 /* LegacyCDMSession.h in Headers */,
30575
				CDF4B7121E0087AE00E235A2 /* LegacyCDMSession.h in Headers */,
30568
				CDE8B5F11A69778B00B4B66A /* LegacyCDMSessionClearKey.h in Headers */,
30576
				CDE8B5F11A69778B00B4B66A /* LegacyCDMSessionClearKey.h in Headers */,
Lines 30815-30821 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec7
30815
				1A7FA6190DDA3B3A0028F8A5 /* NetworkStateNotifier.h in Headers */,
30823
				1A7FA6190DDA3B3A0028F8A5 /* NetworkStateNotifier.h in Headers */,
30816
				E13EF3441684ECF40034C83F /* NetworkStorageSession.h in Headers */,
30824
				E13EF3441684ECF40034C83F /* NetworkStorageSession.h in Headers */,
30817
				269397241A4A5B6400E8349D /* NFA.h in Headers */,
30825
				269397241A4A5B6400E8349D /* NFA.h in Headers */,
30818
				E4E94D6122FF158A00DD191F /* ComplexLineLayout.h in Headers */,
30819
				269397221A4A412F00E8349D /* NFANode.h in Headers */,
30826
				269397221A4A412F00E8349D /* NFANode.h in Headers */,
30820
				267726011A5B3AD9003C24DD /* NFAToDFA.h in Headers */,
30827
				267726011A5B3AD9003C24DD /* NFAToDFA.h in Headers */,
30821
				BCEF43DD0E674012001C1287 /* NinePieceImage.h in Headers */,
30828
				BCEF43DD0E674012001C1287 /* NinePieceImage.h in Headers */,
- a/Source/WebCore/css/parser/CSSParser.cpp +5 lines
Lines 167-172 Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const Strin a/Source/WebCore/css/parser/CSSParser.cpp_sec1
167
    return CSSParserImpl::parseInlineStyleDeclaration(string, element);
167
    return CSSParserImpl::parseInlineStyleDeclaration(string, element);
168
}
168
}
169
169
170
Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const String& string, const CSSParserMode& mode)
171
{
172
    return CSSParserImpl::parseInlineStyleDeclaration(string, mode);
173
}
174
170
bool CSSParser::parseDeclaration(MutableStyleProperties& declaration, const String& string)
175
bool CSSParser::parseDeclaration(MutableStyleProperties& declaration, const String& string)
171
{
176
{
172
    return CSSParserImpl::parseDeclarationList(&declaration, string, m_context);
177
    return CSSParserImpl::parseDeclarationList(&declaration, string, m_context);
- a/Source/WebCore/css/parser/CSSParser.h +1 lines
Lines 75-80 public: a/Source/WebCore/css/parser/CSSParser.h_sec1
75
75
76
    WEBCORE_EXPORT bool parseDeclaration(MutableStyleProperties&, const String&);
76
    WEBCORE_EXPORT bool parseDeclaration(MutableStyleProperties&, const String&);
77
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*);
77
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*);
78
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const CSSParserMode&);
78
79
79
    void parseSelector(const String&, CSSSelectorList&);
80
    void parseSelector(const String&, CSSSelectorList&);
80
81
- a/Source/WebCore/css/parser/CSSParserImpl.cpp +9 lines
Lines 166-171 Ref<ImmutableStyleProperties> CSSParserImpl::parseInlineStyleDeclaration(const S a/Source/WebCore/css/parser/CSSParserImpl.cpp_sec1
166
    return createStyleProperties(parser.m_parsedProperties, context.mode);
166
    return createStyleProperties(parser.m_parsedProperties, context.mode);
167
}
167
}
168
168
169
Ref<ImmutableStyleProperties> CSSParserImpl::parseInlineStyleDeclaration(const String& string, const CSSParserMode& mode)
170
{
171
    CSSParserContext context(mode);
172
173
    CSSParserImpl parser(context, string);
174
    parser.consumeDeclarationList(parser.tokenizer()->tokenRange(), StyleRule::Style);
175
    return createStyleProperties(parser.m_parsedProperties, context.mode);
176
}
177
169
Ref<ImmutableStyleProperties> CSSParserImpl::parseDeferredDeclaration(CSSParserTokenRange tokenRange, const CSSParserContext& context, StyleSheetContents* styleSheet)
178
Ref<ImmutableStyleProperties> CSSParserImpl::parseDeferredDeclaration(CSSParserTokenRange tokenRange, const CSSParserContext& context, StyleSheetContents* styleSheet)
170
{
179
{
171
    if (!styleSheet) {
180
    if (!styleSheet) {
- a/Source/WebCore/css/parser/CSSParserImpl.h +1 lines
Lines 85-90 public: a/Source/WebCore/css/parser/CSSParserImpl.h_sec1
85
    static CSSParser::ParseResult parseValue(MutableStyleProperties*, CSSPropertyID, const String&, bool important, const CSSParserContext&);
85
    static CSSParser::ParseResult parseValue(MutableStyleProperties*, CSSPropertyID, const String&, bool important, const CSSParserContext&);
86
    static CSSParser::ParseResult parseCustomPropertyValue(MutableStyleProperties*, const AtomString& propertyName, const String&, bool important, const CSSParserContext&);
86
    static CSSParser::ParseResult parseCustomPropertyValue(MutableStyleProperties*, const AtomString& propertyName, const String&, bool important, const CSSParserContext&);
87
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*);
87
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*);
88
    static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const CSSParserMode&);
88
    static bool parseDeclarationList(MutableStyleProperties*, const String&, const CSSParserContext&);
89
    static bool parseDeclarationList(MutableStyleProperties*, const String&, const CSSParserContext&);
89
    static RefPtr<StyleRuleBase> parseRule(const String&, const CSSParserContext&, StyleSheetContents*, AllowedRulesType);
90
    static RefPtr<StyleRuleBase> parseRule(const String&, const CSSParserContext&, StyleSheetContents*, AllowedRulesType);
90
    static void parseStyleSheet(const String&, const CSSParserContext&, StyleSheetContents*, CSSParser::RuleParsing);
91
    static void parseStyleSheet(const String&, const CSSParserContext&, StyleSheetContents*, CSSParser::RuleParsing);
- a/Source/WebCore/dom/Document.cpp +8 lines
Lines 117-122 a/Source/WebCore/dom/Document.cpp_sec1
117
#include "KeyboardEvent.h"
117
#include "KeyboardEvent.h"
118
#include "KeyframeEffect.h"
118
#include "KeyframeEffect.h"
119
#include "LayoutDisallowedScope.h"
119
#include "LayoutDisallowedScope.h"
120
#include "LazyLoadImageObserver.h"
120
#include "LibWebRTCProvider.h"
121
#include "LibWebRTCProvider.h"
121
#include "LoaderStrategy.h"
122
#include "LoaderStrategy.h"
122
#include "Logging.h"
123
#include "Logging.h"
Lines 8266-8269 void Document::setApplePayIsActive() a/Source/WebCore/dom/Document.cpp_sec2
8266
8267
8267
#endif
8268
#endif
8268
8269
8270
LazyLoadImageObserver& Document::ensureLazyLoadImageObserver()
8271
{
8272
    if (!m_lazyLoadImageObserver)
8273
        m_lazyLoadImageObserver = new LazyLoadImageObserver();
8274
    return *m_lazyLoadImageObserver;
8275
}
8276
8269
} // namespace WebCore
8277
} // namespace WebCore
- a/Source/WebCore/dom/Document.h +5 lines
Lines 149-154 class IntPoint; a/Source/WebCore/dom/Document.h_sec1
149
class JSNode;
149
class JSNode;
150
class LayoutPoint;
150
class LayoutPoint;
151
class LayoutRect;
151
class LayoutRect;
152
class LazyLoadImageObserver;
152
class LiveNodeList;
153
class LiveNodeList;
153
class Locale;
154
class Locale;
154
class Location;
155
class Location;
Lines 1529-1534 public: a/Source/WebCore/dom/Document.h_sec2
1529
    bool inHitTesting() const { return m_inHitTesting; }
1530
    bool inHitTesting() const { return m_inHitTesting; }
1530
#endif
1531
#endif
1531
1532
1533
    LazyLoadImageObserver& ensureLazyLoadImageObserver();
1534
1532
protected:
1535
protected:
1533
    enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
1536
    enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
1534
    Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
1537
    Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
Lines 1716-1721 private: a/Source/WebCore/dom/Document.h_sec3
1716
1719
1717
    Element* m_cssTarget { nullptr };
1720
    Element* m_cssTarget { nullptr };
1718
1721
1722
    LazyLoadImageObserver* m_lazyLoadImageObserver { nullptr };
1723
1719
    RefPtr<SerializedScriptValue> m_pendingStateObject;
1724
    RefPtr<SerializedScriptValue> m_pendingStateObject;
1720
    MonotonicTime m_documentCreationTime;
1725
    MonotonicTime m_documentCreationTime;
1721
    bool m_overMinimumLayoutThreshold { false };
1726
    bool m_overMinimumLayoutThreshold { false };
- a/Source/WebCore/html/HTMLImageElement.cpp -3 / +41 lines
Lines 68-74 WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLImageElement); a/Source/WebCore/html/HTMLImageElement.cpp_sec1
68
68
69
using namespace HTMLNames;
69
using namespace HTMLNames;
70
70
71
HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
71
HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser)
72
    : HTMLElement(tagName, document)
72
    : HTMLElement(tagName, document)
73
    , m_imageLoader(*this)
73
    , m_imageLoader(*this)
74
    , m_form(nullptr)
74
    , m_form(nullptr)
Lines 76-81 HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& docum a/Source/WebCore/html/HTMLImageElement.cpp_sec2
76
    , m_compositeOperator(CompositeSourceOver)
76
    , m_compositeOperator(CompositeSourceOver)
77
    , m_imageDevicePixelRatio(1.0f)
77
    , m_imageDevicePixelRatio(1.0f)
78
    , m_experimentalImageMenuEnabled(false)
78
    , m_experimentalImageMenuEnabled(false)
79
    , m_createdByParser(createdByParser)
79
{
80
{
80
    ASSERT(hasTagName(imgTag));
81
    ASSERT(hasTagName(imgTag));
81
    setHasCustomStyleResolveCallbacks();
82
    setHasCustomStyleResolveCallbacks();
Lines 86-94 Ref<HTMLImageElement> HTMLImageElement::create(Document& document) a/Source/WebCore/html/HTMLImageElement.cpp_sec3
86
    return adoptRef(*new HTMLImageElement(imgTag, document));
87
    return adoptRef(*new HTMLImageElement(imgTag, document));
87
}
88
}
88
89
89
Ref<HTMLImageElement> HTMLImageElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
90
Ref<HTMLImageElement> HTMLImageElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser)
90
{
91
{
91
    return adoptRef(*new HTMLImageElement(tagName, document, form));
92
    return adoptRef(*new HTMLImageElement(tagName, document, form, createdByParser));
92
}
93
}
93
94
94
HTMLImageElement::~HTMLImageElement()
95
HTMLImageElement::~HTMLImageElement()
Lines 242-247 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomStrin a/Source/WebCore/html/HTMLImageElement.cpp_sec4
242
#endif
243
#endif
243
    } else if (name == x_apple_editable_imageAttr)
244
    } else if (name == x_apple_editable_imageAttr)
244
        updateEditableImage();
245
        updateEditableImage();
246
    else if (name == loadingAttr && equalLettersIgnoringASCIICase(value, "eager"))
247
        loadDeferredImage();
245
    else {
248
    else {
246
        if (name == nameAttr) {
249
        if (name == nameAttr) {
247
            bool willHaveName = !value.isNull();
250
            bool willHaveName = !value.isNull();
Lines 834-837 void HTMLImageElement::defaultEventHandler(Event& event) a/Source/WebCore/html/HTMLImageElement.cpp_sec5
834
    HTMLElement::defaultEventHandler(event);
837
    HTMLElement::defaultEventHandler(event);
835
}
838
}
836
839
840
void HTMLImageElement::loadDeferredImage()
841
{
842
    m_imageLoader.loadDeferredImage();
843
}
844
845
// Minimum height or width of the image to start lazyloading.
846
constexpr int kMinDimensionToLazyLoad = 10;
847
848
HTMLImageElement::LazyLoadDimensionType HTMLImageElement::getAttributeLazyLoadDimensionType(const String& attributeValue)
849
{
850
    auto optionalDimension = parseValidHTMLNonNegativeInteger(attributeValue);
851
    if (optionalDimension && !attributeValue.endsWith('%')) {
852
        return (optionalDimension.value() <= kMinDimensionToLazyLoad)
853
            ? LazyLoadDimensionType::AbsoluteSmall
854
            : LazyLoadDimensionType::AbsoluteNotSmall;
855
    }
856
    return LazyLoadDimensionType::NotAbsolute;
857
}
858
859
HTMLImageElement::LazyLoadDimensionType HTMLImageElement::getInlineStyleDimensionsType(const StyleProperties* propertySet)
860
{
861
    if (!propertySet)
862
        return LazyLoadDimensionType::NotAbsolute;
863
    auto height = propertySet->getPropertyCSSValue(CSSPropertyHeight);
864
    auto width = propertySet->getPropertyCSSValue(CSSPropertyWidth);
865
    if (!height || !height->isPrimitiveValue() || !width || !width->isPrimitiveValue())
866
        return LazyLoadDimensionType::NotAbsolute;
867
    const auto& widthPrim = downcast<CSSPrimitiveValue>(*width);
868
    const auto& heightPrim = downcast<CSSPrimitiveValue>(*height);
869
    if (!widthPrim.isPx() || !heightPrim.isPx())
870
        return LazyLoadDimensionType::NotAbsolute;
871
    return (heightPrim.doubleValue() <= kMinDimensionToLazyLoad) && (widthPrim.doubleValue() <= kMinDimensionToLazyLoad)
872
        ? LazyLoadDimensionType::AbsoluteSmall : LazyLoadDimensionType::AbsoluteNotSmall;
873
}
874
837
}
875
}
- a/Source/WebCore/html/HTMLImageElement.h -2 / +19 lines
Lines 44-50 class HTMLImageElement : public HTMLElement, public FormNamedItem { a/Source/WebCore/html/HTMLImageElement.h_sec1
44
    friend class HTMLFormElement;
44
    friend class HTMLFormElement;
45
public:
45
public:
46
    static Ref<HTMLImageElement> create(Document&);
46
    static Ref<HTMLImageElement> create(Document&);
47
    static Ref<HTMLImageElement> create(const QualifiedName&, Document&, HTMLFormElement*);
47
    static Ref<HTMLImageElement> create(const QualifiedName&, Document&, HTMLFormElement* = nullptr, bool createdByParser = false);
48
    static Ref<HTMLImageElement> createForJSConstructor(Document&, Optional<unsigned> width, Optional<unsigned> height);
48
    static Ref<HTMLImageElement> createForJSConstructor(Document&, Optional<unsigned> width, Optional<unsigned> height);
49
49
50
    virtual ~HTMLImageElement();
50
    virtual ~HTMLImageElement();
Lines 123-130 public: a/Source/WebCore/html/HTMLImageElement.h_sec2
123
123
124
    void defaultEventHandler(Event&) final;
124
    void defaultEventHandler(Event&) final;
125
125
126
    void loadDeferredImage();
127
128
    bool createdByParser() const { return m_createdByParser; }
129
130
    // Returns dimension type of the attribute value or inline dimensions usable
131
    // for LazyLoad, whether the dimension is absolute or not and if the absolute
132
    // value is small enough to be skipped for lazyloading.
133
    enum class LazyLoadDimensionType {
134
        NotAbsolute,
135
        AbsoluteNotSmall,
136
        AbsoluteSmall,
137
    };
138
139
    static LazyLoadDimensionType getAttributeLazyLoadDimensionType(const String& attributeValue);
140
    static LazyLoadDimensionType getInlineStyleDimensionsType(const StyleProperties*);
141
126
protected:
142
protected:
127
    HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement* = 0);
143
    HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement* = nullptr, bool createdByParser = false);
128
144
129
    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;
145
    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;
130
146
Lines 183-188 private: a/Source/WebCore/html/HTMLImageElement.h_sec3
183
    float m_imageDevicePixelRatio;
199
    float m_imageDevicePixelRatio;
184
    bool m_experimentalImageMenuEnabled;
200
    bool m_experimentalImageMenuEnabled;
185
    bool m_hadNameBeforeAttributeChanged { false }; // FIXME: We only need this because parseAttribute() can't see the old value.
201
    bool m_hadNameBeforeAttributeChanged { false }; // FIXME: We only need this because parseAttribute() can't see the old value.
202
    bool m_createdByParser { false };
186
203
187
    RefPtr<EditableImageReference> m_editableImage;
204
    RefPtr<EditableImageReference> m_editableImage;
188
    WeakPtr<HTMLPictureElement> m_pictureElement;
205
    WeakPtr<HTMLPictureElement> m_pictureElement;
- a/Source/WebCore/html/HTMLTagNames.in -1 / +1 lines
Lines 68-74 html a/Source/WebCore/html/HTMLTagNames.in_sec1
68
i interfaceName=HTMLElement
68
i interfaceName=HTMLElement
69
iframe interfaceName=HTMLIFrameElement
69
iframe interfaceName=HTMLIFrameElement
70
image interfaceName=HTMLUnknownElement
70
image interfaceName=HTMLUnknownElement
71
img interfaceName=HTMLImageElement, constructorNeedsFormElement
71
img interfaceName=HTMLImageElement, constructorNeedsFormElement, constructorNeedsCreatedByParser
72
input constructorNeedsFormElement, constructorNeedsCreatedByParser
72
input constructorNeedsFormElement, constructorNeedsCreatedByParser
73
ins interfaceName=HTMLModElement
73
ins interfaceName=HTMLModElement
74
kbd interfaceName=HTMLElement
74
kbd interfaceName=HTMLElement
- a/Source/WebCore/html/LazyLoadImageObserver.cpp +105 lines
Line 0 a/Source/WebCore/html/LazyLoadImageObserver.cpp_sec1
1
/*
2
 * Copyright (C) 2019 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "LazyLoadImageObserver.h"
28
29
#include "Frame.h"
30
#include "HTMLImageElement.h"
31
#include "IntersectionObserverCallback.h"
32
#include "RenderStyle.h"
33
34
#include <limits>
35
36
namespace WebCore {
37
38
class IntersectionObserverCallbackImpl final : public IntersectionObserverCallback {
39
public:
40
    static Ref<IntersectionObserverCallbackImpl> create(Document* document)
41
    {
42
        return adoptRef(*new IntersectionObserverCallbackImpl(document));
43
    }
44
    IntersectionObserverCallbackImpl(Document* document)
45
        : IntersectionObserverCallback(document), m_document(document)
46
    {
47
    }
48
    CallbackResult<void> handleEvent(const Vector<Ref<IntersectionObserverEntry>>& entries, IntersectionObserver&)
49
    {
50
        ASSERT(!entries.isEmpty());
51
52
        for (auto& entry : entries) {
53
            if (!entry->isIntersecting())
54
                continue;
55
            Element* element = entry->target();
56
            if (is<HTMLImageElement>(element))
57
                downcast<HTMLImageElement>(*element).loadDeferredImage();
58
59
            m_document->ensureLazyLoadImageObserver().stopMonitoring(*element);
60
        }
61
        return { };
62
    }
63
private:
64
    Document* m_document;
65
};
66
67
namespace {
68
69
Document* getRootDocumentOrNull(const Element& element)
70
{
71
    if (Frame* frame = element.document().frame())
72
        return frame->tree().top().document();
73
    return nullptr;
74
}
75
76
} // namespace
77
78
void LazyLoadImageObserver::startMonitoring(Element& element)
79
{
80
    if (Document* document = getRootDocumentOrNull(element))
81
        document->ensureLazyLoadImageObserver().startMonitoringNearViewport(document, element);
82
}
83
84
void LazyLoadImageObserver::stopMonitoring(Element& element)
85
{
86
    if (Document* document = getRootDocumentOrNull(element))
87
        document->ensureLazyLoadImageObserver().m_lazyLoadIntersectionObserver->unobserve(element);
88
}
89
90
LazyLoadImageObserver::LazyLoadImageObserver() = default;
91
92
void LazyLoadImageObserver::startMonitoringNearViewport(Document* rootDocument, Element& element)
93
{
94
    if (!m_lazyLoadIntersectionObserver) {
95
        auto callback = IntersectionObserverCallbackImpl::create(rootDocument);
96
        auto options = IntersectionObserver::Init { nullptr, "", { } };
97
        auto observer = IntersectionObserver::create(*rootDocument, WTFMove(callback), WTFMove(options));
98
        if (observer.hasException())
99
            return;
100
        m_lazyLoadIntersectionObserver = observer.returnValue().ptr();
101
    }
102
    m_lazyLoadIntersectionObserver->observe(element);
103
}
104
105
}
- a/Source/WebCore/html/LazyLoadImageObserver.h +50 lines
Line 0 a/Source/WebCore/html/LazyLoadImageObserver.h_sec1
1
/*
2
 * Copyright (C) 2019 Igalia S.L.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#include "IntersectionObserver.h"
29
30
namespace WebCore {
31
32
class Document;
33
class Element;
34
35
class LazyLoadImageObserver {
36
public:
37
    LazyLoadImageObserver();
38
39
    static void startMonitoring(Element&);
40
    static void stopMonitoring(Element&);
41
42
private:
43
    void startMonitoringNearViewport(Document*, Element&);
44
45
    // The intersection observer responsible for loading the image once it's near
46
    // the viewport.
47
    RefPtr<IntersectionObserver> m_lazyLoadIntersectionObserver;
48
};
49
50
} // namespace
- a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp +38 lines
Lines 28-33 a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp_sec1
28
#include "config.h"
28
#include "config.h"
29
#include "HTMLPreloadScanner.h"
29
#include "HTMLPreloadScanner.h"
30
30
31
#include "HTMLImageElement.h"
31
#include "HTMLNames.h"
32
#include "HTMLNames.h"
32
#include "HTMLParserIdioms.h"
33
#include "HTMLParserIdioms.h"
33
#include "HTMLSrcsetParser.h"
34
#include "HTMLSrcsetParser.h"
Lines 43-48 a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp_sec2
43
#include "RenderView.h"
44
#include "RenderView.h"
44
#include "RuntimeEnabledFeatures.h"
45
#include "RuntimeEnabledFeatures.h"
45
#include "SizesAttributeParser.h"
46
#include "SizesAttributeParser.h"
47
#include "StyleProperties.h"
46
#include <wtf/MainThread.h>
48
#include <wtf/MainThread.h>
47
49
48
namespace WebCore {
50
namespace WebCore {
Lines 161-166 public: a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp_sec3
161
        if (!LinkLoader::isSupportedType(type.value(), m_typeAttribute))
163
        if (!LinkLoader::isSupportedType(type.value(), m_typeAttribute))
162
            return nullptr;
164
            return nullptr;
163
165
166
        // Do not preload if lazyload is possible but metadata fetch is disabled.
167
        if (equalLettersIgnoringASCIICase(m_lazyloadAttribute, "lazy"))
168
            return nullptr;
169
170
        // LazyLoad: Do not preload if absolute dimensions are mentioned in width
171
        // and height attributes or in the inline style, and the dimensions are not
172
        // small enough.
173
        if (((m_widthAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall
174
            && m_heightAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)
175
            || m_inlineStyleDimensionsType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)) {
176
            return nullptr;
177
        }
178
164
        auto request = std::make_unique<PreloadRequest>(initiatorFor(m_tagId), m_urlToLoad, predictedBaseURL, type.value(), m_mediaAttribute, m_moduleScript, m_referrerPolicy);
179
        auto request = std::make_unique<PreloadRequest>(initiatorFor(m_tagId), m_urlToLoad, predictedBaseURL, type.value(), m_mediaAttribute, m_moduleScript, m_referrerPolicy);
165
        request->setCrossOriginMode(m_crossOriginMode);
180
        request->setCrossOriginMode(m_crossOriginMode);
166
        request->setNonce(m_nonceAttribute);
181
        request->setNonce(m_nonceAttribute);
Lines 206-211 private: a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp_sec4
206
                m_sizesAttribute = attributeValue;
221
                m_sizesAttribute = attributeValue;
207
                break;
222
                break;
208
            }
223
            }
224
            if (match(attributeName, loadingAttr) && m_lazyloadAttribute.isNull()) {
225
                m_lazyloadAttribute = attributeValue;
226
                break;
227
            }
228
            if (RuntimeEnabledFeatures::sharedFeatures().lazyImageLoadingEnabled()) {
229
                if (match(attributeName, widthAttr) && m_widthAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) {
230
                    m_widthAttrDimensionType = HTMLImageElement::getAttributeLazyLoadDimensionType(attributeValue);
231
                    break;
232
                }
233
                if (match(attributeName, heightAttr) && m_heightAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) {
234
                    m_heightAttrDimensionType = HTMLImageElement::getAttributeLazyLoadDimensionType(attributeValue);
235
                    break;
236
                }
237
                if (match(attributeName, styleAttr) && m_inlineStyleDimensionsType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) {
238
                    CSSParserMode mode = /*media_values_->StrictMode() ? HTMLStandardMode :*/ HTMLQuirksMode;
239
                    const auto propertySet = CSSParser::parseInlineStyleDeclaration(attributeValue, mode);
240
                    m_inlineStyleDimensionsType = HTMLImageElement::getInlineStyleDimensionsType(propertySet.ptr());
241
                }
242
            }
209
            processImageAndScriptAttribute(attributeName, attributeValue);
243
            processImageAndScriptAttribute(attributeName, attributeValue);
210
            break;
244
            break;
211
        case TagId::Source:
245
        case TagId::Source:
Lines 370-378 private: a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp_sec5
370
    String m_metaContent;
404
    String m_metaContent;
371
    String m_asAttribute;
405
    String m_asAttribute;
372
    String m_typeAttribute;
406
    String m_typeAttribute;
407
    String m_lazyloadAttribute;
373
    bool m_metaIsViewport;
408
    bool m_metaIsViewport;
374
    bool m_metaIsDisabledAdaptations;
409
    bool m_metaIsDisabledAdaptations;
375
    bool m_inputIsImage;
410
    bool m_inputIsImage;
411
    HTMLImageElement::LazyLoadDimensionType m_widthAttrDimensionType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute };
412
    HTMLImageElement::LazyLoadDimensionType m_heightAttrDimensionType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute };
413
    HTMLImageElement::LazyLoadDimensionType m_inlineStyleDimensionsType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute };
376
    float m_deviceScaleFactor;
414
    float m_deviceScaleFactor;
377
    PreloadRequest::ModuleScript m_moduleScript { PreloadRequest::ModuleScript::No };
415
    PreloadRequest::ModuleScript m_moduleScript { PreloadRequest::ModuleScript::No };
378
    ReferrerPolicy m_referrerPolicy { ReferrerPolicy::EmptyString };
416
    ReferrerPolicy m_referrerPolicy { ReferrerPolicy::EmptyString };
- a/Source/WebCore/html/parser/HTMLPreloadScanner.h +6 lines
Lines 81-86 private: a/Source/WebCore/html/parser/HTMLPreloadScanner.h_sec1
81
    unsigned m_templateCount { 0 };
81
    unsigned m_templateCount { 0 };
82
};
82
};
83
83
84
enum class LazyLoadImageSetting {
85
    Disabled,
86
    EnabledExplicit,
87
    EnabledAutomatic
88
};
89
84
class HTMLPreloadScanner {
90
class HTMLPreloadScanner {
85
    WTF_MAKE_FAST_ALLOCATED;
91
    WTF_MAKE_FAST_ALLOCATED;
86
public:
92
public:
- a/Source/WebCore/loader/ImageLoader.cpp -1 / +75 lines
Lines 38-46 a/Source/WebCore/loader/ImageLoader.cpp_sec1
38
#include "HTMLObjectElement.h"
38
#include "HTMLObjectElement.h"
39
#include "HTMLParserIdioms.h"
39
#include "HTMLParserIdioms.h"
40
#include "InspectorInstrumentation.h"
40
#include "InspectorInstrumentation.h"
41
#include "LazyLoadImageObserver.h"
41
#include "Page.h"
42
#include "Page.h"
42
#include "RenderImage.h"
43
#include "RenderImage.h"
43
#include "RenderSVGImage.h"
44
#include "RenderSVGImage.h"
45
#include "RuntimeEnabledFeatures.h"
44
#include <wtf/NeverDestroyed.h>
46
#include <wtf/NeverDestroyed.h>
45
47
46
#if ENABLE(VIDEO)
48
#if ENABLE(VIDEO)
Lines 66-71 template<> struct ValueCheck<WebCore::ImageLoader*> { a/Source/WebCore/loader/ImageLoader.cpp_sec2
66
68
67
namespace WebCore {
69
namespace WebCore {
68
70
71
static bool isLazyLoadableImage(const HTMLImageElement& htmlImage, const URL& url)
72
{
73
    // Do not lazyload image elements created from javascript.
74
    if (!htmlImage.createdByParser())
75
        return false;
76
    if (!url.protocolIsInHTTPFamily())
77
        return false;
78
    if (!equalLettersIgnoringASCIICase(htmlImage.attributeWithoutSynchronization(HTMLNames::loadingAttr), "lazy"))
79
        return false;
80
    // Avoid lazyloading if width and height attributes are small. This
81
    // heuristic helps avoid double fetching tracking pixels.
82
    if (HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::widthAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall
83
        && HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::heightAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall) {
84
        return false;
85
    }
86
    // Avoid lazyloading if width or height is specified in inline style and is
87
    // small enough. This heuristic helps avoid double fetching tracking pixels.
88
    if (HTMLImageElement::getInlineStyleDimensionsType(htmlImage.inlineStyle()) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall)
89
        return false;
90
    return true;
91
}
92
69
static ImageEventSender& beforeLoadEventSender()
93
static ImageEventSender& beforeLoadEventSender()
70
{
94
{
71
    static NeverDestroyed<ImageEventSender> sender(eventNames().beforeloadEvent);
95
    static NeverDestroyed<ImageEventSender> sender(eventNames().beforeloadEvent);
Lines 157-162 void ImageLoader::clearImageWithoutConsideringPendingLoadEvent() a/Source/WebCore/loader/ImageLoader.cpp_sec3
157
        imageResource->resetAnimation();
181
        imageResource->resetAnimation();
158
}
182
}
159
183
184
// Returns true if absolute dimension is specified in the width and height
185
// attributes or in the inline style.
186
static bool isDimensionAbsoluteLarge(const HTMLImageElement& htmlImage)
187
{
188
    if ((HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::widthAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)
189
        || (HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::heightAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)) {
190
        return true;
191
    }
192
    if (HTMLImageElement::getInlineStyleDimensionsType(htmlImage.inlineStyle()) == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)
193
        return true;
194
    return false;
195
}
196
160
void ImageLoader::updateFromElement()
197
void ImageLoader::updateFromElement()
161
{
198
{
162
    // If we're not making renderers for the page, then don't load images. We don't want to slow
199
    // If we're not making renderers for the page, then don't load images. We don't want to slow
Lines 183-188 void ImageLoader::updateFromElement() a/Source/WebCore/loader/ImageLoader.cpp_sec4
183
220
184
        ResourceRequest resourceRequest(document.completeURL(sourceURI(attr)));
221
        ResourceRequest resourceRequest(document.completeURL(sourceURI(attr)));
185
        resourceRequest.setInspectorInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(m_element));
222
        resourceRequest.setInspectorInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(m_element));
223
        bool defer = false;
224
        if (m_lazyImageLoadState == LazyImageLoadState::kNone) {
225
            if (is<HTMLImageElement>(element())) {
226
                if (isLazyLoadableImage(downcast<HTMLImageElement>(element()), resourceRequest.url())
227
                    && RuntimeEnabledFeatures::sharedFeatures().lazyImageLoadingEnabled()) {
228
                    m_lazyImageLoadState = LazyImageLoadState::kDeferred;
229
                    if (!isDimensionAbsoluteLarge(downcast<HTMLImageElement>(element())))
230
                        defer = true;
231
                }
232
            }
233
        }
186
234
187
        auto request = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, crossOriginAttribute, WTFMove(options));
235
        auto request = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, crossOriginAttribute, WTFMove(options));
188
        request.setInitiator(element());
236
        request.setInitiator(element());
Lines 197-203 void ImageLoader::updateFromElement() a/Source/WebCore/loader/ImageLoader.cpp_sec5
197
            document.cachedResourceLoader().m_documentResources.set(newImage->url(), newImage.get());
245
            document.cachedResourceLoader().m_documentResources.set(newImage->url(), newImage.get());
198
            document.cachedResourceLoader().setAutoLoadImages(autoLoadOtherImages);
246
            document.cachedResourceLoader().setAutoLoadImages(autoLoadOtherImages);
199
        } else
247
        } else
200
            newImage = document.cachedResourceLoader().requestImage(WTFMove(request)).value_or(nullptr);
248
            newImage = document.cachedResourceLoader().requestImage(WTFMove(request), defer).value_or(nullptr);
201
249
202
        // If we do not have an image here, it means that a cross-site
250
        // If we do not have an image here, it means that a cross-site
203
        // violation occurred, or that the image was blocked via Content
251
        // violation occurred, or that the image was blocked via Content
Lines 250-255 void ImageLoader::updateFromElement() a/Source/WebCore/loader/ImageLoader.cpp_sec6
250
            } else
298
            } else
251
                updateRenderer();
299
                updateRenderer();
252
300
301
            if (m_lazyImageLoadState == LazyImageLoadState::kDeferred)
302
                LazyLoadImageObserver::startMonitoring(element());
303
253
            // If newImage is cached, addClient() will result in the load event
304
            // If newImage is cached, addClient() will result in the load event
254
            // being queued to fire. Ensure this happens after beforeload is
305
            // being queued to fire. Ensure this happens after beforeload is
255
            // dispatched.
306
            // dispatched.
Lines 280-285 void ImageLoader::notifyFinished(CachedResource& resource) a/Source/WebCore/loader/ImageLoader.cpp_sec7
280
    ASSERT(m_failedLoadURL.isEmpty());
331
    ASSERT(m_failedLoadURL.isEmpty());
281
    ASSERT_UNUSED(resource, &resource == m_image.get());
332
    ASSERT_UNUSED(resource, &resource == m_image.get());
282
333
334
    if (m_lazyImageLoadState == LazyImageLoadState::kDeferred) {
335
        // LazyImages: if a placeholder is loaded, suppress load events and do not
336
        // consider the image as loaded, except for unblocking document load events.
337
        // The final image load (including load events) occurs when the
338
        // non-placeholder image loading (triggered by loadDeferredImage()) is
339
        // finished.
340
        if (resource.response().httpStatusCode() == 206)
341
            return;
342
        // A placeholder was requested, but the result was an error or a full image.
343
        // In these cases, consider this as the final image and suppress further
344
        // reloading and proceed to the image load completion process below.
345
        LazyLoadImageObserver::stopMonitoring(element());
346
        m_lazyImageLoadState = LazyImageLoadState::kFullImage;
347
    }
348
283
    m_imageComplete = true;
349
    m_imageComplete = true;
284
    if (!hasPendingBeforeLoadEvent())
350
    if (!hasPendingBeforeLoadEvent())
285
        updateRenderer();
351
        updateRenderer();
Lines 542-545 inline void ImageLoader::clearFailedLoadURL() a/Source/WebCore/loader/ImageLoader.cpp_sec8
542
    m_failedLoadURL = nullAtom();
608
    m_failedLoadURL = nullAtom();
543
}
609
}
544
610
611
void ImageLoader::loadDeferredImage()
612
{
613
    if (m_lazyImageLoadState != LazyImageLoadState::kDeferred)
614
        return;
615
    m_lazyImageLoadState = LazyImageLoadState::kFullImage;
616
    updateFromElement();
617
}
618
545
}
619
}
- a/Source/WebCore/loader/ImageLoader.h +6 lines
Lines 74-84 public: a/Source/WebCore/loader/ImageLoader.h_sec1
74
    static void dispatchPendingLoadEvents();
74
    static void dispatchPendingLoadEvents();
75
    static void dispatchPendingErrorEvents();
75
    static void dispatchPendingErrorEvents();
76
76
77
    void loadDeferredImage();
78
77
protected:
79
protected:
78
    explicit ImageLoader(Element&);
80
    explicit ImageLoader(Element&);
79
    void notifyFinished(CachedResource&) override;
81
    void notifyFinished(CachedResource&) override;
80
82
81
private:
83
private:
84
    // LazyImages: Defer the image load until the image is near the viewport.
85
    enum class LazyImageLoadState { kNone, kDeferred, kFullImage };
86
82
    virtual void dispatchLoadEvent() = 0;
87
    virtual void dispatchLoadEvent() = 0;
83
    virtual String sourceURI(const AtomString&) const = 0;
88
    virtual String sourceURI(const AtomString&) const = 0;
84
89
Lines 112-117 private: a/Source/WebCore/loader/ImageLoader.h_sec2
112
    bool m_imageComplete : 1;
117
    bool m_imageComplete : 1;
113
    bool m_loadManually : 1;
118
    bool m_loadManually : 1;
114
    bool m_elementIsProtected : 1;
119
    bool m_elementIsProtected : 1;
120
    LazyImageLoadState m_lazyImageLoadState { LazyImageLoadState::kNone };
115
};
121
};
116
122
117
}
123
}
- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp -3 / +4 lines
Lines 197-203 PAL::SessionID CachedResourceLoader::sessionID() const a/Source/WebCore/loader/cache/CachedResourceLoader.cpp_sec1
197
    return sessionID;
197
    return sessionID;
198
}
198
}
199
199
200
ResourceErrorOr<CachedResourceHandle<CachedImage>> CachedResourceLoader::requestImage(CachedResourceRequest&& request)
200
ResourceErrorOr<CachedResourceHandle<CachedImage>> CachedResourceLoader::requestImage(CachedResourceRequest&& request, bool defer)
201
{
201
{
202
    if (Frame* frame = this->frame()) {
202
    if (Frame* frame = this->frame()) {
203
        if (frame->loader().pageDismissalEventBeingDispatched() != FrameLoader::PageDismissalType::None) {
203
        if (frame->loader().pageDismissalEventBeingDispatched() != FrameLoader::PageDismissalType::None) {
Lines 210-217 ResourceErrorOr<CachedResourceHandle<CachedImage>> CachedResourceLoader::request a/Source/WebCore/loader/cache/CachedResourceLoader.cpp_sec2
210
        }
210
        }
211
    }
211
    }
212
212
213
    auto defer = clientDefersImage(request.resourceRequest().url()) ? DeferOption::DeferredByClient : DeferOption::NoDefer;
213
    if (!defer)
214
    return castCachedResourceTo<CachedImage>(requestResource(CachedResource::Type::ImageResource, WTFMove(request), ForPreload::No, defer));
214
        defer = clientDefersImage(request.resourceRequest().url());
215
    return castCachedResourceTo<CachedImage>(requestResource(CachedResource::Type::ImageResource, WTFMove(request), ForPreload::No, defer ? DeferOption::DeferredByClient : DeferOption::NoDefer));
215
}
216
}
216
217
217
ResourceErrorOr<CachedResourceHandle<CachedFont>> CachedResourceLoader::requestFont(CachedResourceRequest&& request, bool isSVG)
218
ResourceErrorOr<CachedResourceHandle<CachedFont>> CachedResourceLoader::requestFont(CachedResourceRequest&& request, bool isSVG)
- a/Source/WebCore/loader/cache/CachedResourceLoader.h -1 / +1 lines
Lines 79-85 public: a/Source/WebCore/loader/cache/CachedResourceLoader.h_sec1
79
    static Ref<CachedResourceLoader> create(DocumentLoader* documentLoader) { return adoptRef(*new CachedResourceLoader(documentLoader)); }
79
    static Ref<CachedResourceLoader> create(DocumentLoader* documentLoader) { return adoptRef(*new CachedResourceLoader(documentLoader)); }
80
    ~CachedResourceLoader();
80
    ~CachedResourceLoader();
81
81
82
    ResourceErrorOr<CachedResourceHandle<CachedImage>> requestImage(CachedResourceRequest&&);
82
    ResourceErrorOr<CachedResourceHandle<CachedImage>> requestImage(CachedResourceRequest&&, bool defer = false);
83
    ResourceErrorOr<CachedResourceHandle<CachedCSSStyleSheet>> requestCSSStyleSheet(CachedResourceRequest&&);
83
    ResourceErrorOr<CachedResourceHandle<CachedCSSStyleSheet>> requestCSSStyleSheet(CachedResourceRequest&&);
84
    CachedResourceHandle<CachedCSSStyleSheet> requestUserCSSStyleSheet(Page&, CachedResourceRequest&&);
84
    CachedResourceHandle<CachedCSSStyleSheet> requestUserCSSStyleSheet(Page&, CachedResourceRequest&&);
85
    ResourceErrorOr<CachedResourceHandle<CachedScript>> requestScript(CachedResourceRequest&&);
85
    ResourceErrorOr<CachedResourceHandle<CachedScript>> requestScript(CachedResourceRequest&&);
- a/Tools/ChangeLog +11 lines
Lines 1-3 a/Tools/ChangeLog_sec1
1
2019-08-13  Rob Buis  <rbuis@igalia.com>
2
3
        Support lazy image and iframe loading (loading="lazy")
4
        https://bugs.webkit.org/show_bug.cgi?id=196698
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * WebKitTestRunner/TestController.cpp:
9
        (WTR::TestController::resetPreferencesToConsistentValues):
10
        (WTR::updateTestOptionsFromTestHeader):
11
1
2019-08-12  Takashi Komori  <Takashi.Komori@sony.com>
12
2019-08-12  Takashi Komori  <Takashi.Komori@sony.com>
2
13
3
        [WTF] Thread::removeFromThreadGroup leaks weak pointers.
14
        [WTF] Thread::removeFromThreadGroup leaks weak pointers.
- a/Tools/WebKitTestRunner/TestController.cpp -3 lines
Lines 821-827 void TestController::resetPreferencesToConsistentValues(const TestOptions& optio a/Tools/WebKitTestRunner/TestController.cpp_sec1
821
    WKPreferencesSetColorFilterEnabled(preferences, options.enableColorFilter);
821
    WKPreferencesSetColorFilterEnabled(preferences, options.enableColorFilter);
822
    WKPreferencesSetPunchOutWhiteBackgroundsInDarkMode(preferences, options.punchOutWhiteBackgroundsInDarkMode);
822
    WKPreferencesSetPunchOutWhiteBackgroundsInDarkMode(preferences, options.punchOutWhiteBackgroundsInDarkMode);
823
    WKPreferencesSetPageCacheEnabled(preferences, options.enablePageCache);
823
    WKPreferencesSetPageCacheEnabled(preferences, options.enablePageCache);
824
    WKPreferencesSetLazyImageLoadingEnabled(preferences, options.enableLazyImageLoading);
825
824
826
    static WKStringRef defaultTextEncoding = WKStringCreateWithUTF8CString("ISO-8859-1");
825
    static WKStringRef defaultTextEncoding = WKStringCreateWithUTF8CString("ISO-8859-1");
827
    WKPreferencesSetDefaultTextEncodingName(preferences, defaultTextEncoding);
826
    WKPreferencesSetDefaultTextEncodingName(preferences, defaultTextEncoding);
Lines 1401-1408 static void updateTestOptionsFromTestHeader(TestOptions& testOptions, const std: a/Tools/WebKitTestRunner/TestController.cpp_sec2
1401
            testOptions.enableAppNap = parseBooleanTestHeaderValue(value);
1400
            testOptions.enableAppNap = parseBooleanTestHeaderValue(value);
1402
        else if (key == "enablePageCache")
1401
        else if (key == "enablePageCache")
1403
            testOptions.enablePageCache = parseBooleanTestHeaderValue(value);
1402
            testOptions.enablePageCache = parseBooleanTestHeaderValue(value);
1404
        else if (key == "enableLazyImageLoading")
1405
            testOptions.enableLazyImageLoading = parseBooleanTestHeaderValue(value);
1406
        pairStart = pairEnd + 1;
1403
        pairStart = pairEnd + 1;
1407
    }
1404
    }
1408
}
1405
}
- a/LayoutTests/ChangeLog +9 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2019-08-13  Rob Buis  <rbuis@igalia.com>
2
3
        Support lazy image and iframe loading (loading="lazy")
4
        https://bugs.webkit.org/show_bug.cgi?id=196698
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * TestExpectations:
9
1
2019-08-12  Ryosuke Niwa  <rniwa@webkit.org>
10
2019-08-12  Ryosuke Niwa  <rniwa@webkit.org>
2
11
3
        FrameLoader::open can execute scritps via style recalc in Frame::setDocument
12
        FrameLoader::open can execute scritps via style recalc in Frame::setDocument
- a/LayoutTests/imported/w3c/ChangeLog +12 lines
Lines 1-3 a/LayoutTests/imported/w3c/ChangeLog_sec1
1
2019-08-13  Rob Buis  <rbuis@igalia.com>
2
3
        Support lazy image and iframe loading (loading="lazy")
4
        https://bugs.webkit.org/show_bug.cgi?id=196698
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Set correct test option.
9
10
        * web-platform-tests/loading/lazyload/image-loading-lazy.tentative-expected.txt: Added.
11
        * web-platform-tests/loading/lazyload/image-loading-lazy.tentative.html:
12
1
2019-08-08  Rob Buis  <rbuis@igalia.com>
13
2019-08-08  Rob Buis  <rbuis@igalia.com>
2
14
3
        Import lazy loading WPT tests
15
        Import lazy loading WPT tests
- a/LayoutTests/TestExpectations -1 lines
Lines 3465-3469 fast/text/design-system-ui-14.html [ ImageOnlyFailure ] a/LayoutTests/TestExpectations_sec1
3465
fast/text/design-system-ui-15.html [ ImageOnlyFailure ]
3465
fast/text/design-system-ui-15.html [ ImageOnlyFailure ]
3466
fast/text/design-system-ui-16.html [ ImageOnlyFailure ]
3466
fast/text/design-system-ui-16.html [ ImageOnlyFailure ]
3467
3467
3468
webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative.html
3469
webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/iframe-loading-lazy.tentative.html
3468
webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/iframe-loading-lazy.tentative.html
- a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative-expected.txt +5 lines
Line 0 a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative-expected.txt_sec1
1
2
3
4
PASS Test that images with loading='lazy' load once they enter the viewport. 
5
- a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative.html -1 / +1 lines
Lines 1-4 a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative.html_sec1
1
<!DOCTYPE html>
1
<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] -->
2
<head>
2
<head>
3
  <title>Images with loading='lazy' load when in the viewport</title>
3
  <title>Images with loading='lazy' load when in the viewport</title>
4
  <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org">
4
  <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org">

Return to Bug 196698