Skip to content

Commit

Permalink
V1: mount/unmount concept and automatic scheduling
Browse files Browse the repository at this point in the history
  • Loading branch information
Dima Voytenko committed Mar 15, 2021
1 parent fe48afd commit 43a7725
Show file tree
Hide file tree
Showing 11 changed files with 437 additions and 162 deletions.
57 changes: 39 additions & 18 deletions builtins/amp-img.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export class AmpImg extends BaseElement {
return true;
}

/** @override @nocollapse */
static load() {
return true;
}

/** @override @nocollapse */
static getPreconnects(element) {
const src = element.getAttribute('src');
Expand Down Expand Up @@ -176,10 +181,11 @@ export class AmpImg extends BaseElement {
/**
* Create the actual image element and set up instance variables.
* Called lazily in the first `#layoutCallback`.
* @return {!Image}
*/
initialize_() {
if (this.img_) {
return;
return this.img_;
}
// If this amp-img IS the fallback then don't allow it to have its own
// fallback to stop from nested fallback abuse.
Expand Down Expand Up @@ -219,6 +225,7 @@ export class AmpImg extends BaseElement {
propagateObjectFitStyles(this.element, this.img_);

this.element.appendChild(this.img_);
return this.img_;
}

/**
Expand Down Expand Up @@ -294,29 +301,43 @@ export class AmpImg extends BaseElement {
}

/** @override */
buildCallback() {
if (!AmpImg.V1()) {
return;
mountCallback() {
const initialized = !!this.img_;
const img = this.initialize_();
if (!initialized) {
listen(img, 'load', () => {
this.setReadyState(ReadyState.COMPLETE);
this.firstLayoutCompleted();
this.hideFallbackImg_();
});
listen(img, 'error', (reason) => {
this.setReadyState(ReadyState.ERROR, reason);
this.onImgLoadingError_();
});
}

// A V1 amp-img loads and reloads automatically.
this.setReadyState(ReadyState.LOADING);
this.initialize_();
const img = dev().assertElement(this.img_);
if (img.complete) {
this.setReadyState(ReadyState.COMPLETE);
this.firstLayoutCompleted();
this.hideFallbackImg_();
} else {
this.setReadyState(ReadyState.LOADING);
}
listen(img, 'load', () => {
this.setReadyState(ReadyState.COMPLETE);
this.firstLayoutCompleted();
this.hideFallbackImg_();
});
listen(img, 'error', (reason) => {
this.setReadyState(ReadyState.ERROR, reason);
this.onImgLoadingError_();
});
}

/** @override */
unmountCallback() {
// Interrupt retrieval of incomplete images to free network resources when
// navigating pages in a PWA. Opt for tiny dataURI image instead of empty
// src to prevent the viewer from detecting a load error.
const img = this.img_;
if (img && !img.complete) {
img.src =
'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=';
removeElement(img);
this.img_ = null;
}

return true;
}

/** @override */
Expand Down
32 changes: 32 additions & 0 deletions src/base-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ export class BaseElement {
return false;
}

/**
* Subclasses can override this method to indicate that an element can load
* network resources.
*
* Such elements can have their `ensureLoaded` method called.
*
* @param {!AmpElement} unusedElement
* @return {boolean}
* @nocollapse
*/
static load(unusedElement) {
return false;
}

/**
* Subclasses can override this method to provide a svg logo that will be
* displayed as the loader.
Expand Down Expand Up @@ -513,6 +527,24 @@ export class BaseElement {
this.element.setReadyStateInternal(state, opt_failure);
}

/**
* Load heavy elements, perform expensive operations, add global
* listeners/observers, etc.
*
* @param {!AbortSignal=} opt_abortSignal
* @return {?Promise|undefined}
*/
mountCallback(opt_abortSignal) {}

/**
* Unload heavy elements, remove global listeners, etc.
*
* @return {boolean}
*/
unmountCallback() {
return false;
}

/**
* Subclasses can override this method to opt-in into receiving additional
* {@link layoutCallback} calls. Note that this method is not consulted for
Expand Down
5 changes: 5 additions & 0 deletions src/common-signals.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export const CommonSignals = {
*/
BUILT: 'built',

/**
* The element has been mounted.
*/
MOUNTED: 'mounted',

/**
* The element has started loading.
* LOAD_START triggers at the start of the layoutCallback.
Expand Down
Loading

0 comments on commit 43a7725

Please sign in to comment.