From 486988eb6ec351a217c656e4cebbc5958b7b73a6 Mon Sep 17 00:00:00 2001
From: Kristofer Baxter
Date: Tue, 27 Apr 2021 09:03:04 -0700
Subject: [PATCH 01/48] Allow IMG so long as it contains a loading attribute
---
validator/validator-main.protoascii | 33 +++++++++++++++--------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/validator/validator-main.protoascii b/validator/validator-main.protoascii
index d05715f0f734..88bcc5954c18 100644
--- a/validator/validator-main.protoascii
+++ b/validator/validator-main.protoascii
@@ -1740,12 +1740,10 @@ tags: {
# and transformed amp-img.
# 4.7.1 The img element
tags: {
- html_format: AMP # Disallowed in AMP4ADS because
+
diff --git a/examples/image-lightbox.amp.html b/examples/image-lightbox.amp.html
index 25e861cf1ba8..d08d1b3304d6 100644
--- a/examples/image-lightbox.amp.html
+++ b/examples/image-lightbox.amp.html
@@ -22,6 +22,13 @@
+
+
diff --git a/extensions/amp-anim/0.1/amp-anim.js b/extensions/amp-anim/0.1/amp-anim.js
index 47205b27615c..283fe960f7ef 100644
--- a/extensions/amp-anim/0.1/amp-anim.js
+++ b/extensions/amp-anim/0.1/amp-anim.js
@@ -22,6 +22,7 @@ import {
observeWithSharedInOb,
unobserveWithSharedInOb,
} from '../../../src/viewport-observer';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {propagateObjectFitStyles} from '../../../src/style';
const TAG = 'amp-anim';
@@ -55,7 +56,7 @@ export class AmpAnim extends AMP.BaseElement {
buildCallback() {
this.img_ = new Image();
this.img_.setAttribute('decoding', 'async');
- this.propagateAttributes(BUILD_ATTRIBUTES, this.img_);
+ propagateAttributes(BUILD_ATTRIBUTES, this.element, this.img_);
this.applyFillContent(this.img_, true);
propagateObjectFitStyles(this.element, this.img_);
@@ -88,8 +89,9 @@ export class AmpAnim extends AMP.BaseElement {
const img = dev().assertElement(this.img_);
// Remove missing attributes to remove the placeholder srcset if none is
// specified on the element.
- this.propagateAttributes(
+ propagateAttributes(
LAYOUT_ATTRIBUTES,
+ this.element,
img,
/* opt_removeMissingAttrs */ true
);
diff --git a/extensions/amp-audio/0.1/amp-audio.js b/extensions/amp-audio/0.1/amp-audio.js
index 9491dfaeba9f..d62e6c835ce7 100644
--- a/extensions/amp-audio/0.1/amp-audio.js
+++ b/extensions/amp-audio/0.1/amp-audio.js
@@ -28,6 +28,7 @@ import {closestAncestorElementBySelector} from '../../../src/dom';
import {dev, user} from '../../../src/log';
import {getMode} from '../../../src/mode';
import {listen} from '../../../src/event-helper';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setIsMediaComponent} from '../../../src/video-interface';
import {triggerAnalyticsEvent} from '../../../src/analytics';
@@ -85,7 +86,11 @@ export class AmpAudio extends AMP.BaseElement {
if (src !== undefined) {
assertHttpsUrl(src, this.element);
}
- this.propagateAttributes(['src', 'loop', 'controlsList'], this.audio_);
+ propagateAttributes(
+ ['src', 'loop', 'controlsList'],
+ this.element,
+ this.audio_
+ );
}
const artist = mutations['artist'];
@@ -119,7 +124,7 @@ export class AmpAudio extends AMP.BaseElement {
if (src) {
assertHttpsUrl(src, this.element);
}
- this.propagateAttributes(
+ propagateAttributes(
[
'src',
'preload',
@@ -131,6 +136,7 @@ export class AmpAudio extends AMP.BaseElement {
'aria-labelledby',
'controlsList',
],
+ this.element,
audio
);
diff --git a/extensions/amp-brid-player/0.1/amp-brid-player.js b/extensions/amp-brid-player/0.1/amp-brid-player.js
index aeb911faa396..4e5df8ab3afc 100644
--- a/extensions/amp-brid-player/0.1/amp-brid-player.js
+++ b/extensions/amp-brid-player/0.1/amp-brid-player.js
@@ -42,6 +42,7 @@ import {getData, listen} from '../../../src/event-helper';
import {htmlFor} from '../../../src/static-template';
import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
const TAG = 'amp-brid-player';
@@ -249,7 +250,7 @@ class AmpBridPlayer extends AMP.BaseElement {
`;
- this.propagateAttributes(['aria-label'], placeholder);
+ propagateAttributes(['aria-label'], this.element, placeholder);
this.applyFillContent(placeholder);
placeholder.setAttribute(
diff --git a/extensions/amp-gfycat/0.1/amp-gfycat.js b/extensions/amp-gfycat/0.1/amp-gfycat.js
index 51184d730e70..6c1133920fc1 100644
--- a/extensions/amp-gfycat/0.1/amp-gfycat.js
+++ b/extensions/amp-gfycat/0.1/amp-gfycat.js
@@ -26,6 +26,7 @@ import {
import {getData, listen} from '../../../src/event-helper';
import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
const TAG = 'amp-gfycat';
@@ -89,7 +90,7 @@ class AmpGfycat extends AMP.BaseElement {
createPlaceholderCallback() {
const placeholder = this.win.document.createElement('amp-img');
const videoid = dev().assertString(this.videoid_);
- this.propagateAttributes(['alt', 'aria-label'], placeholder);
+ propagateAttributes(['alt', 'aria-label'], this.element, placeholder);
placeholder.setAttribute(
'src',
'https://thumbs.gfycat.com/' + encodeURIComponent(videoid) + '-poster.jpg'
diff --git a/extensions/amp-google-document-embed/0.1/amp-google-document-embed.js b/extensions/amp-google-document-embed/0.1/amp-google-document-embed.js
index 45ba247a2082..74a91fd88305 100644
--- a/extensions/amp-google-document-embed/0.1/amp-google-document-embed.js
+++ b/extensions/amp-google-document-embed/0.1/amp-google-document-embed.js
@@ -31,6 +31,7 @@ import {Services} from '../../../src/services';
import {addParamToUrl} from '../../../src/url';
import {dev, userAssert} from '../../../src/log';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {removeElement} from '../../../src/dom';
export const TAG = 'amp-google-document-embed';
@@ -90,7 +91,7 @@ export class AmpDriveViewer extends AMP.BaseElement {
iframe.setAttribute('frameborder', '0');
iframe.setAttribute('allowfullscreen', '');
- this.propagateAttributes(ATTRIBUTES_TO_PROPAGATE, iframe);
+ propagateAttributes(ATTRIBUTES_TO_PROPAGATE, this.element, iframe);
iframe.src = this.getSrc_(this.element.getAttribute('src'));
@@ -105,7 +106,12 @@ export class AmpDriveViewer extends AMP.BaseElement {
(value) => mutations[value] !== undefined
);
const iframe = dev().assertElement(this.iframe_);
- this.propagateAttributes(attrs, iframe, /* opt_removeMissingAttrs */ true);
+ propagateAttributes(
+ attrs,
+ this.element,
+ iframe,
+ /* opt_removeMissingAttrs */ true
+ );
const src = mutations['src'];
if (src) {
iframe.src = this.getSrc_(src);
diff --git a/extensions/amp-iframe/0.1/amp-iframe.js b/extensions/amp-iframe/0.1/amp-iframe.js
index 3ca6243a3810..2e9cfb015e28 100644
--- a/extensions/amp-iframe/0.1/amp-iframe.js
+++ b/extensions/amp-iframe/0.1/amp-iframe.js
@@ -36,6 +36,7 @@ import {isAdPositionAllowed} from '../../../src/ad-helper';
import {isExperimentOn} from '../../../src/experiments';
import {moveLayoutRect} from '../../../src/layout-rect';
import {parseJson} from '../../../src/json';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {removeElement} from '../../../src/dom';
import {removeFragment} from '../../../src/url';
import {setStyle} from '../../../src/style';
@@ -414,7 +415,7 @@ export class AmpIframe extends AMP.BaseElement {
setStyle(iframe, 'zIndex', -1);
}
- this.propagateAttributes(ATTRIBUTES_TO_PROPAGATE, iframe);
+ propagateAttributes(ATTRIBUTES_TO_PROPAGATE, this.element, iframe);
// TEMPORARY: disable `allow=autoplay`
// This is a workaround for M72-M74 user-activation breakage.
@@ -619,7 +620,7 @@ export class AmpIframe extends AMP.BaseElement {
}
if (this.iframe_ && mutations['title']) {
// only propagating title because propagating all causes e2e error:
- this.propagateAttributes(['title'], this.iframe_);
+ propagateAttributes(['title'], this.element, this.iframe_);
}
}
diff --git a/extensions/amp-image-lightbox/0.1/amp-image-lightbox.js b/extensions/amp-image-lightbox/0.1/amp-image-lightbox.js
index 20b9cf424496..4a03deb4c68b 100644
--- a/extensions/amp-image-lightbox/0.1/amp-image-lightbox.js
+++ b/extensions/amp-image-lightbox/0.1/amp-image-lightbox.js
@@ -39,6 +39,7 @@ import {
layoutRectLtwh,
moveLayoutRect,
} from '../../../src/layout-rect';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setStyles, toggle} from '../../../src/style';
import {srcsetFromElement} from '../../../src/srcset';
@@ -49,6 +50,11 @@ const SUPPORTED_ELEMENTS_ = {
'amp-img': true,
'amp-anim': true,
};
+/** @private @const {!Object} */
+const SUPPORTED_NATIVE_ELEMENTS = {
+ 'img': true,
+ 'picture': true,
+};
/** @private @const */
const ARIA_ATTRIBUTES = ['aria-label', 'aria-describedby', 'aria-labelledby'];
@@ -253,9 +259,15 @@ export class ImageViewer {
this.setSourceDimensions_(sourceElement, sourceImage);
this.srcset_ = srcsetFromElement(sourceElement);
- sourceElement.getImpl().then((elem) => {
- elem.propagateAttributes(ARIA_ATTRIBUTES, this.image_);
- });
+ if (SUPPORTED_NATIVE_ELEMENTS[sourceElement.tagName.toLowerCase()]) {
+ propagateAttributes(ARIA_ATTRIBUTES, sourceElement, this.image_);
+ } else {
+ sourceElement
+ .getImpl()
+ .then((elem) =>
+ propagateAttributes(ARIA_ATTRIBUTES, elem, this.image_)
+ );
+ }
if (sourceImage && isLoaded(sourceImage) && sourceImage.src) {
// Set src provisionally to the known loaded value for fast display.
@@ -871,8 +883,10 @@ class AmpImageLightbox extends AMP.BaseElement {
this.buildLightbox_();
const source = invocation.caller;
+ const tagName = source.tagName.toLowerCase();
userAssert(
- source && SUPPORTED_ELEMENTS_[source.tagName.toLowerCase()],
+ source &&
+ (SUPPORTED_ELEMENTS_[tagName] || SUPPORTED_NATIVE_ELEMENTS[tagName]),
'Unsupported element: %s',
source.tagName
);
diff --git a/extensions/amp-image-viewer/0.1/amp-image-viewer.js b/extensions/amp-image-viewer/0.1/amp-image-viewer.js
index ef66ccf7c829..329e9c58f5f9 100644
--- a/extensions/amp-image-viewer/0.1/amp-image-viewer.js
+++ b/extensions/amp-image-viewer/0.1/amp-image-viewer.js
@@ -46,6 +46,7 @@ import {
observeContentSize,
unobserveContentSize,
} from '../../../src/utils/size-observer';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setStyles} from '../../../src/style';
import {srcsetFromElement} from '../../../src/srcset';
@@ -321,7 +322,7 @@ export class AmpImageViewer extends AMP.BaseElement {
st.toggle(ampImg, false);
this.element.appendChild(this.image_);
return ampImg.getImpl().then((ampImg) => {
- ampImg.propagateAttributes(ARIA_ATTRIBUTES, this.image_);
+ propagateAttributes(ARIA_ATTRIBUTES, ampImg, this.image_);
});
});
}
diff --git a/extensions/amp-inline-gallery/0.1/amp-inline-gallery-thumbnails.js b/extensions/amp-inline-gallery/0.1/amp-inline-gallery-thumbnails.js
index 2115ec6e9321..4f481fd9fd6b 100644
--- a/extensions/amp-inline-gallery/0.1/amp-inline-gallery-thumbnails.js
+++ b/extensions/amp-inline-gallery/0.1/amp-inline-gallery-thumbnails.js
@@ -21,6 +21,7 @@ import {dict} from '../../../src/core/types/object';
import {htmlFor} from '../../../src/static-template';
import {isLayoutSizeDefined} from '../../../src/layout';
import {matches, scopedQuerySelector} from '../../../src/dom';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setStyle} from '../../../src/style';
/**
@@ -246,7 +247,7 @@ export class AmpInlineGalleryThumbnails extends AMP.BaseElement {
// We create with loop defaulting to false above, and allow it to be
// overwriten.
- this.propagateAttributes(['loop'], this.carousel_);
+ propagateAttributes(['loop'], this.element, this.carousel_);
this.element.appendChild(this.carousel_);
}
}
diff --git a/extensions/amp-jwplayer/0.1/amp-jwplayer.js b/extensions/amp-jwplayer/0.1/amp-jwplayer.js
index 7b07fd651423..19db0da600e6 100644
--- a/extensions/amp-jwplayer/0.1/amp-jwplayer.js
+++ b/extensions/amp-jwplayer/0.1/amp-jwplayer.js
@@ -42,6 +42,7 @@ import {getMode} from '../../../src/mode';
import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl';
import {isLayoutSizeDefined} from '../../../src/layout';
import {once} from '../../../src/core/types/function';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
const JWPLAYER_EVENTS = {
'ready': VideoEvents.LOAD,
@@ -349,7 +350,7 @@ class AmpJWPlayer extends AMP.BaseElement {
return;
}
const placeholder = this.win.document.createElement('amp-img');
- this.propagateAttributes(['aria-label'], placeholder);
+ propagateAttributes(['aria-label'], this.element, placeholder);
placeholder.setAttribute(
'src',
'https://content.jwplatform.com/thumbs/' +
diff --git a/extensions/amp-kaltura-player/0.1/amp-kaltura-player.js b/extensions/amp-kaltura-player/0.1/amp-kaltura-player.js
index 8dfb63e07cb0..a09abd15eae4 100644
--- a/extensions/amp-kaltura-player/0.1/amp-kaltura-player.js
+++ b/extensions/amp-kaltura-player/0.1/amp-kaltura-player.js
@@ -20,6 +20,7 @@ import {addParamsToUrl} from '../../../src/url';
import {dict} from '../../../src/core/types/object';
import {getDataParamsFromAttributes} from '../../../src/dom';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setIsMediaComponent} from '../../../src/video-interface';
import {userAssert} from '../../../src/log';
@@ -125,7 +126,7 @@ class AmpKaltura extends AMP.BaseElement {
/** @override */
createPlaceholderCallback() {
const placeholder = this.win.document.createElement('amp-img');
- this.propagateAttributes(['aria-label'], placeholder);
+ propagateAttributes(['aria-label'], this.element, placeholder);
const width = this.element.getAttribute('width');
const height = this.element.getAttribute('height');
let src = `https://${encodeURIComponent(
diff --git a/extensions/amp-springboard-player/0.1/amp-springboard-player.js b/extensions/amp-springboard-player/0.1/amp-springboard-player.js
index 16db5bb51b8f..013b9694c4df 100644
--- a/extensions/amp-springboard-player/0.1/amp-springboard-player.js
+++ b/extensions/amp-springboard-player/0.1/amp-springboard-player.js
@@ -17,6 +17,7 @@
import {PauseHelper} from '../../../src/utils/pause-helper';
import {Services} from '../../../src/services';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setIsMediaComponent} from '../../../src/video-interface';
import {userAssert} from '../../../src/log';
@@ -154,7 +155,7 @@ class AmpSpringboardPlayer extends AMP.BaseElement {
/** @override */
createPlaceholderCallback() {
const placeholder = this.win.document.createElement('amp-img');
- this.propagateAttributes(['aria-label'], placeholder);
+ propagateAttributes(['aria-label'], this.element, placeholder);
placeholder.setAttribute(
'src',
'https://www.springboardplatform.com/storage/' +
diff --git a/extensions/amp-story/1.0/amp-story-page.js b/extensions/amp-story/1.0/amp-story-page.js
index ff4777ecb182..dc380abc928c 100644
--- a/extensions/amp-story/1.0/amp-story-page.js
+++ b/extensions/amp-story/1.0/amp-story-page.js
@@ -75,6 +75,7 @@ import {isExperimentOn} from '../../../src/experiments';
import {isPrerenderActivePage} from './prerender-active-page';
import {listen} from '../../../src/event-helper';
import {CSS as pageAttachmentCSS} from '../../../build/amp-story-open-page-attachment-0.1.css';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {px, toggle} from '../../../src/style';
import {renderPageAttachmentUI} from './amp-story-open-page-attachment';
import {renderPageDescription} from './semantic-render';
@@ -1857,7 +1858,7 @@ export class AmpStoryPage extends AMP.BaseElement {
childImgNode &&
ampImgNode
.getImpl()
- .then((ampImg) => ampImg.propagateAttributes('alt', childImgNode));
+ .then((ampImg) => propagateAttributes('alt', ampImg, childImgNode));
}
});
}
diff --git a/extensions/amp-video/0.1/amp-video.js b/extensions/amp-video/0.1/amp-video.js
index 69e6684cd211..fe76abd4ea02 100644
--- a/extensions/amp-video/0.1/amp-video.js
+++ b/extensions/amp-video/0.1/amp-video.js
@@ -41,6 +41,7 @@ import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl
import {isLayoutSizeDefined} from '../../../src/layout';
import {listen, listenOncePromise} from '../../../src/event-helper';
import {mutedOrUnmutedEvent} from '../../../src/iframe-video';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {
propagateObjectFitStyles,
setImportantStyles,
@@ -234,8 +235,9 @@ export class AmpVideo extends AMP.BaseElement {
// Disable video preload in prerender mode.
this.video_.setAttribute('preload', 'none');
this.checkA11yAttributeText_();
- this.propagateAttributes(
+ propagateAttributes(
ATTRS_TO_PROPAGATE_ON_BUILD,
+ this.element,
this.video_,
/* opt_removeMissingAttrs */ true
);
@@ -313,13 +315,18 @@ export class AmpVideo extends AMP.BaseElement {
if (mutations['src']) {
const urlService = this.getUrlService_();
urlService.assertHttpsUrl(element.getAttribute('src'), element);
- this.propagateAttributes(['src'], dev().assertElement(this.video_));
+ propagateAttributes(
+ ['src'],
+ this.element,
+ dev().assertElement(this.video_)
+ );
}
const attrs = ATTRS_TO_PROPAGATE.filter(
(value) => mutations[value] !== undefined
);
- this.propagateAttributes(
+ propagateAttributes(
attrs,
+ this.element,
dev().assertElement(this.video_),
/* opt_removeMissingAttrs */ true
);
@@ -357,8 +364,9 @@ export class AmpVideo extends AMP.BaseElement {
return Promise.resolve();
}
- this.propagateAttributes(
+ propagateAttributes(
ATTRS_TO_PROPAGATE_ON_LAYOUT,
+ this.element,
dev().assertElement(this.video_),
/* opt_removeMissingAttrs */ true
);
@@ -539,7 +547,11 @@ export class AmpVideo extends AMP.BaseElement {
// If the `src` of `amp-video` itself is NOT cached, set it on video
if (element.hasAttribute('src') && !isCachedByCdn(element)) {
urlService.assertHttpsUrl(element.getAttribute('src'), element);
- this.propagateAttributes(['src'], dev().assertElement(this.video_));
+ propagateAttributes(
+ ['src'],
+ this.element,
+ dev().assertElement(this.video_)
+ );
}
sources.forEach((source) => {
diff --git a/extensions/amp-viqeo-player/0.1/amp-viqeo-player.js b/extensions/amp-viqeo-player/0.1/amp-viqeo-player.js
index 05cb4f3fe9c0..b1c1599aee06 100644
--- a/extensions/amp-viqeo-player/0.1/amp-viqeo-player.js
+++ b/extensions/amp-viqeo-player/0.1/amp-viqeo-player.js
@@ -31,6 +31,7 @@ import {
import {getData, listen} from '../../../src/event-helper';
import {getIframe} from '../../../src/3p-frame';
import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
const TAG = 'amp-viqeo-player';
@@ -205,7 +206,7 @@ class AmpViqeoPlayer extends AMP.BaseElement {
/** @override */
createPlaceholderCallback() {
const placeholder = this.element.ownerDocument.createElement('amp-img');
- this.propagateAttributes(['aria-label'], placeholder);
+ propagateAttributes(['aria-label'], this.element, placeholder);
if (placeholder.hasAttribute('aria-label')) {
placeholder.setAttribute(
'alt',
diff --git a/extensions/amp-youtube/0.1/amp-youtube.js b/extensions/amp-youtube/0.1/amp-youtube.js
index 95a4a335a804..8026133a7385 100644
--- a/extensions/amp-youtube/0.1/amp-youtube.js
+++ b/extensions/amp-youtube/0.1/amp-youtube.js
@@ -42,6 +42,7 @@ import {getData, listen} from '../../../src/event-helper';
import {htmlFor} from '../../../src/static-template';
import {installVideoManagerForDoc} from '../../../src/service/video-manager-impl';
import {isLayoutSizeDefined} from '../../../src/layout';
+import {propagateAttributes} from '../../../src/core/dom/propagateAttributes';
import {setStyles} from '../../../src/style';
const TAG = 'amp-youtube';
@@ -497,7 +498,7 @@ class AmpYoutube extends AMP.BaseElement {
// the object-fit: cover.
'visibility': 'hidden',
});
- this.propagateAttributes(['aria-label'], imgPlaceholder);
+ propagateAttributes(['aria-label'], this.element, imgPlaceholder);
// TODO(mkhatib): Maybe add srcset to allow the browser to
// load the needed size or even better match YTPlayer logic for loading
// player thumbnails for different screen sizes for a cache win!
diff --git a/src/base-element.js b/src/base-element.js
index a5183a995777..fd1138155c0d 100644
--- a/src/base-element.js
+++ b/src/base-element.js
@@ -749,29 +749,6 @@ export class BaseElement {
}
}
- /**
- * Utility method that propagates attributes from this element
- * to the given element.
- * If `opt_removeMissingAttrs` is true, then also removes any specified
- * attributes that are missing on this element from the target element.
- * @param {string|!Array} attributes
- * @param {!Element} element
- * @param {boolean=} opt_removeMissingAttrs
- * @public @final
- */
- propagateAttributes(attributes, element, opt_removeMissingAttrs) {
- attributes = isArray(attributes) ? attributes : [attributes];
- for (let i = 0; i < attributes.length; i++) {
- const attr = attributes[i];
- const val = this.element.getAttribute(attr);
- if (null !== val) {
- element.setAttribute(attr, val);
- } else if (opt_removeMissingAttrs) {
- element.removeAttribute(attr);
- }
- }
- }
-
/**
* Utility method that forwards the given list of non-bubbling events
* from the given element to this element as custom events with the same name.
diff --git a/src/core/dom/propagateAttributes.js b/src/core/dom/propagateAttributes.js
new file mode 100644
index 000000000000..8e37f354eb3d
--- /dev/null
+++ b/src/core/dom/propagateAttributes.js
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2021 The AMP HTML Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {isArray} from '../types';
+
+/**
+ * Utility method that propagates attributes from a source element
+ * to an updateable element.
+ * If `opt_removeMissingAttrs` is true, then also removes any specified
+ * attributes that are missing on the source element from the updateable element.
+ * @param {string|!Array} attributes
+ * @param {!Element} sourceElement
+ * @param {!Element} updateElement
+ * @param {boolean=} opt_removeMissingAttrs
+ * @public @final
+ */
+export function propagateAttributes(
+ attributes,
+ sourceElement,
+ updateElement,
+ opt_removeMissingAttrs
+) {
+ attributes = isArray(attributes) ? attributes : [attributes];
+ for (let i = 0; i < attributes.length; i++) {
+ const attr = attributes[i];
+ const val = sourceElement.getAttribute(attr);
+ if (null !== val) {
+ updateElement.setAttribute(attr, val);
+ } else if (opt_removeMissingAttrs) {
+ updateElement.removeAttribute(attr);
+ }
+ }
+}
diff --git a/src/iframe-video.js b/src/iframe-video.js
index d0c869e82c12..783a7d234c6c 100644
--- a/src/iframe-video.js
+++ b/src/iframe-video.js
@@ -20,6 +20,7 @@ import {dispatchCustomEvent} from './dom';
import {htmlFor} from './static-template';
import {isArray, isObject} from './core/types';
+import {propagateAttributes} from './core/dom/propagateAttributes';
import {tryParseJson} from './json';
/** @enum {string} */
@@ -91,7 +92,7 @@ export function createFrameFor(video, src, opt_name, opt_sandbox) {
// Will propagate for every component, but only validation rules will actually
// allow the attribute to be set.
- video.propagateAttributes(['referrerpolicy'], frame);
+ propagateAttributes(['referrerpolicy'], video, frame);
frame.src = Services.urlForDoc(element).assertHttpsUrl(src, element);
diff --git a/test/unit/test-base-element.js b/test/unit/test-base-element.js
index 701bd4974d35..b9a49453543d 100644
--- a/test/unit/test-base-element.js
+++ b/test/unit/test-base-element.js
@@ -22,6 +22,7 @@ import {Services} from '../../src/services';
import {createAmpElementForTesting} from '../../src/custom-element';
import {layoutRectLtwh} from '../../src/layout-rect';
import {listenOncePromise} from '../../src/event-helper';
+import {propagateAttributes} from '../../src/core/dom/propagateAttributes';
describes.realWin('BaseElement', {amp: true}, (env) => {
let win, doc;
@@ -54,10 +55,10 @@ describes.realWin('BaseElement', {amp: true}, (env) => {
const target = doc.createElement('div');
expect(target.hasAttributes()).to.be.false;
- element.propagateAttributes(['data-test1'], target);
+ propagateAttributes(['data-test1'], element, target);
expect(target.hasAttributes()).to.be.false;
- element.propagateAttributes(['data-test2', 'data-test3'], target);
+ propagateAttributes(['data-test2', 'data-test3'], element, target);
expect(target.hasAttributes()).to.be.false;
});
@@ -69,14 +70,14 @@ describes.realWin('BaseElement', {amp: true}, (env) => {
customElement.setAttribute('data-test2', 'xyz');
customElement.setAttribute('data-test3', '123');
- element.propagateAttributes('data-test1', target);
+ propagateAttributes('data-test1', element, target);
expect(target.hasAttributes()).to.be.true;
expect(target.getAttribute('data-test1')).to.equal('abc');
expect(target.getAttribute('data-test2')).to.be.null;
expect(target.getAttribute('data-test3')).to.be.null;
- element.propagateAttributes(['data-test2', 'data-test3'], target);
+ propagateAttributes(['data-test2', 'data-test3'], element, target);
expect(target.getAttribute('data-test2')).to.equal('xyz');
expect(target.getAttribute('data-test3')).to.equal('123');
});
From 3412e946563b0954af6a993e3d6754f647637bd8 Mon Sep 17 00:00:00 2001
From: Kristofer Baxter
Date: Tue, 27 Apr 2021 11:06:30 -0700
Subject: [PATCH 04/48] Update validator output
---
.../test/validator-amp-access-laterpay.out | 10 ++++-
.../test/validator-amp-access-laterpay.out | 10 ++++-
.../0.1/test/validator-amp-access.out | 10 ++++-
.../0.1/test/validator-amp-live-list.out | 2 +-
.../test/validator-amp-story-player-error.out | 4 +-
.../validator-amp-story-player-img-error.out | 4 +-
.../validator-amp-story-reference-point.out | 4 +-
validator/testdata/feature_tests/leaks.out | 38 ++++++++++++++-----
validator/testdata/feature_tests/noscript.out | 18 +++++++--
.../transformed_feature_tests/amp-img.out | 8 +++-
.../blurry_image_placeholder.out | 8 +++-
.../server_side_rendering.out | 12 +++++-
12 files changed, 96 insertions(+), 32 deletions(-)
diff --git a/extensions/amp-access-laterpay/0.1/test/validator-amp-access-laterpay.out b/extensions/amp-access-laterpay/0.1/test/validator-amp-access-laterpay.out
index 33f11702d1c5..3c9480c4f9b2 100644
--- a/extensions/amp-access-laterpay/0.1/test/validator-amp-access-laterpay.out
+++ b/extensions/amp-access-laterpay/0.1/test/validator-amp-access-laterpay.out
@@ -1,4 +1,4 @@
-PASS
+FAIL
|
@@ -67,4 +73,4 @@ PASS
|
|
|
-|