Skip to content

Commit

Permalink
Move owners implementation from resources to owners
Browse files Browse the repository at this point in the history
  • Loading branch information
powerivq committed Aug 2, 2019
1 parent 704f49e commit 1bcb889
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 257 deletions.
4 changes: 4 additions & 0 deletions build-system/tasks/presubmit-checks.js
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,10 @@ const forbiddenTerms = {
'src/service/resources-impl.js',
],
},
'\\.scheduleLayoutOrPreload\\(': {
message: 'scheduleLayoutOrPreload is a restricted API.',
whitelist: ['src/service/owners-impl.js', 'src/service/resources-impl.js'],
},
'(win|Win)(dow)?(\\(\\))?\\.open\\W': {
message: 'Use dom.openWindowDialog',
whitelist: ['src/dom.js'],
Expand Down
6 changes: 2 additions & 4 deletions src/inabox/inabox-services.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ import {installHistoryServiceForDoc} from '../service/history-impl';
import {installIframeMessagingClient} from './inabox-iframe-messaging-client';
import {installInaboxCidService} from './inabox-cid';
import {installInaboxViewportService} from './inabox-viewport';
import {
installOwnersServiceForDoc,
installResourcesServiceForDoc,
} from '../service/resources-impl';
import {installOwnersServiceForDoc} from '../service/owners-impl';
import {installResourcesServiceForDoc} from '../service/resources-impl';
import {installStandardActionsForDoc} from '../service/standard-actions-impl';
import {installUrlForDoc} from '../service/url-impl';
import {installUrlReplacementsServiceForDoc} from '../service/url-replacements-impl';
Expand Down
6 changes: 2 additions & 4 deletions src/service/core-services.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ import {installHistoryServiceForDoc} from './history-impl';
import {installImg} from '../../builtins/amp-img';
import {installInputService} from '../input';
import {installLayout} from '../../builtins/amp-layout';
import {
installOwnersServiceForDoc,
installResourcesServiceForDoc,
} from './resources-impl';
import {installOwnersServiceForDoc} from './owners-impl';
import {installPixel} from '../../builtins/amp-pixel';
import {installPlatformService} from './platform-impl';
import {installResourcesServiceForDoc} from './resources-impl';
import {installStandardActionsForDoc} from './standard-actions-impl';
import {installStorageServiceForDoc} from './storage-impl';
import {installTemplatesService} from './template-impl';
Expand Down
197 changes: 189 additions & 8 deletions src/service/owners-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,48 @@
*/

/* eslint-disable no-unused-vars */
import {Resource, ResourceState} from './resource';
import {Services} from '../services';
import {dev, devAssert} from '../log';
import {isArray} from '../types';
import {registerServiceBuilderForDoc} from '../service';

const TAG_ = 'Owners';

/**
* @param {!Element|!Array<!Element>} elements
* @return {!Array<!Element>}
*/
function elements_(elements) {
return /** @type {!Array<!Element>} */ (isArray(elements)
? elements
: [elements]);
}

/**
* TODO(lannka): migrate all methods from OwnersDef to here.
*
* @interface
*/
export class Owners {
/**
* @param {!./ampdoc-impl.AmpDoc} ampdoc
*/
constructor(ampdoc) {
/** @const @private {!./resources-impl.ResourcesDef} */
this.resources_ = Services.resourcesForDoc(ampdoc);
}

/**
* Assigns an owner for the specified element. This means that the resources
* within this element will be managed by the owner and not Resources manager.
* @param {!Element} element
* @param {!AmpElement} owner
* @package
*/
setOwner(element, owner) {}
setOwner(element, owner) {
Resource.setOwner(element, owner);
}

/**
* Schedules preload for the specified sub-elements that are children of the
Expand All @@ -39,7 +67,13 @@ export class Owners {
* @param {!Element} parentElement
* @param {!Element|!Array<!Element>} subElements
*/
schedulePreload(parentElement, subElements) {}
schedulePreload(parentElement, subElements) {
this.scheduleLayoutOrPreloadForSubresources_(
Resource.forElement(parentElement),
/* layout */ false,
elements_(subElements)
);
}

/**
* Schedules layout for the specified sub-elements that are children of the
Expand All @@ -50,7 +84,13 @@ export class Owners {
* @param {!Element} parentElement
* @param {!Element|!Array<!Element>} subElements
*/
scheduleLayout(parentElement, subElements) {}
scheduleLayout(parentElement, subElements) {
this.scheduleLayoutOrPreloadForSubresources_(
Resource.forElement(parentElement),
/* layout */ true,
elements_(subElements)
);
}

/**
* Invokes `unload` on the elements' resource which in turn will invoke
Expand All @@ -59,7 +99,14 @@ export class Owners {
* @param {!Element} parentElement
* @param {!Element|!Array<!Element>} subElements
*/
schedulePause(parentElement, subElements) {}
schedulePause(parentElement, subElements) {
const parentResource = Resource.forElement(parentElement);
subElements = elements_(subElements);

this.discoverResourcesForArray_(parentResource, subElements, resource => {
resource.pause();
});
}

/**
* Invokes `resume` on the elements' resource which in turn will invoke
Expand All @@ -68,7 +115,14 @@ export class Owners {
* @param {!Element} parentElement
* @param {!Element|!Array<!Element>} subElements
*/
scheduleResume(parentElement, subElements) {}
scheduleResume(parentElement, subElements) {
const parentResource = Resource.forElement(parentElement);
subElements = elements_(subElements);

this.discoverResourcesForArray_(parentResource, subElements, resource => {
resource.resume();
});
}

/**
* Schedules unlayout for specified sub-elements that are children of the
Expand All @@ -77,7 +131,14 @@ export class Owners {
* @param {!Element} parentElement
* @param {!Element|!Array<!Element>} subElements
*/
scheduleUnlayout(parentElement, subElements) {}
scheduleUnlayout(parentElement, subElements) {
const parentResource = Resource.forElement(parentElement);
subElements = elements_(subElements);

this.discoverResourcesForArray_(parentResource, subElements, resource => {
resource.unlayout();
});
}

/**
* A parent resource, especially in when it's an owner (see {@link setOwner}),
Expand All @@ -88,6 +149,126 @@ export class Owners {
* @param {!Element|!Array<!Element>} subElements
* @param {boolean} inLocalViewport
*/
updateInViewport(parentElement, subElements, inLocalViewport) {}
updateInViewport(parentElement, subElements, inLocalViewport) {
this.updateInViewportForSubresources_(
Resource.forElement(parentElement),
elements_(subElements),
inLocalViewport
);
}

/**
* @param {!Resource} resource
* @param {boolean} layout
* @param {number} parentPriority
* @private
*/
measureAndScheduleIfAllowed_(resource, layout, parentPriority) {
resource.measure();
if (
resource.getState() === ResourceState.READY_FOR_LAYOUT &&
resource.isDisplayed()
) {
this.resources_.scheduleLayoutOrPreload(resource, layout, parentPriority);
}
}

/**
* Schedules layout or preload for the sub-resources of the specified
* resource.
* @param {!Resource} parentResource
* @param {boolean} layout
* @param {!Array<!Element>} subElements
* @private
*/
scheduleLayoutOrPreloadForSubresources_(parentResource, layout, subElements) {
this.discoverResourcesForArray_(parentResource, subElements, resource => {
if (resource.getState() === ResourceState.NOT_BUILT) {
resource.whenBuilt().then(() => {
this.measureAndScheduleIfAllowed_(
resource,
layout,
parentResource.getLayoutPriority()
);
});
} else {
this.measureAndScheduleIfAllowed_(
resource,
layout,
parentResource.getLayoutPriority()
);
}
});
}

/**
* Finds resources within the parent resource's shallow subtree.
* @param {!Resource} parentResource
* @param {!Array<!Element>} elements
* @param {function(!Resource)} callback
*/
discoverResourcesForArray_(parentResource, elements, callback) {
elements.forEach(element => {
devAssert(parentResource.element.contains(element));
this.discoverResourcesForElement_(element, callback);
});
}

/**
* Updates inViewport state for the specified sub-resources of a resource.
* @param {!Resource} parentResource
* @param {!Array<!Element>} subElements
* @param {boolean} inLocalViewport
* @private
*/
updateInViewportForSubresources_(
parentResource,
subElements,
inLocalViewport
) {
const inViewport = parentResource.isInViewport() && inLocalViewport;
this.discoverResourcesForArray_(parentResource, subElements, resource => {
resource.setInViewport(inViewport);
});
}

/**
* @param {!Element} element
* @param {function(!Resource)} callback
*/
discoverResourcesForElement_(element, callback) {
// Breadth-first search.
if (element.classList.contains('i-amphtml-element')) {
callback(Resource.forElement(element));
// Also schedule amp-element that is a placeholder for the element.
const placeholder = element.getPlaceholder();
if (placeholder) {
this.discoverResourcesForElement_(placeholder, callback);
}
} else {
const ampElements = element.getElementsByClassName('i-amphtml-element');
const seen = [];
for (let i = 0; i < ampElements.length; i++) {
const ampElement = ampElements[i];
let covered = false;
for (let j = 0; j < seen.length; j++) {
if (seen[j].contains(ampElement)) {
covered = true;
break;
}
}
if (!covered) {
seen.push(ampElement);
callback(Resource.forElement(ampElement));
}
}
}
}
}

/**
* @param {!./ampdoc-impl.AmpDoc} ampdoc
*/
export function installOwnersServiceForDoc(ampdoc) {
registerServiceBuilderForDoc(ampdoc, 'owners', Owners);
}
/* eslint-enable no-unused-vars */
Loading

0 comments on commit 1bcb889

Please sign in to comment.