Skip to content
Browse files

Fixes #2039: Polymer.dom.flush now triggers Custom Elements polyfill …

…mutations and includes an api (`Polymer.dom.addDebouncer(debouncer)`) for adding debouncers which should run at flush time. Template rendering debouncers are placed in the flush list.
  • Loading branch information...
1 parent a26247b commit 89a767c1f97bff9d96f063f4ecfee79bc2f87ec1 @sorvell sorvell committed
Showing with 60 additions and 43 deletions.
  1. +50 −11 src/lib/dom-api.html
  2. +10 −32 src/lib/template/templatizer.html
View
61 src/lib/dom-api.html
@@ -24,8 +24,6 @@
var nativeCloneNode = Element.prototype.cloneNode;
var nativeImportNode = Document.prototype.importNode;
- var dirtyRoots = [];
-
var DomApi = function(node) {
this.node = node;
if (this.patch) {
@@ -36,11 +34,7 @@
DomApi.prototype = {
flush: function() {
- for (var i=0, host; i<dirtyRoots.length; i++) {
- host = dirtyRoots[i];
- host.flushDebouncer('_distribute');
- }
- dirtyRoots = [];
+ flush();
},
_lazyDistribute: function(host) {
@@ -48,8 +42,7 @@
// we don't distribute before initial distribution
if (host.shadyRoot && host.shadyRoot._distributionClean) {
host.shadyRoot._distributionClean = false;
- host.debounce('_distribute', host._distributeContent);
- dirtyRoots.push(host);
+ addDebouncer(host.debounce('_distribute', host._distributeContent));
}
},
@@ -773,8 +766,54 @@
}
};
- // make flush available directly.
- Polymer.dom.flush = DomApi.prototype.flush;
+ // flush and debounce exposed as statics on Polymer.dom
+ var flush = Polymer.dom.flush = function() {
+ // first make any pending CE mutations that might trigger debouncer
+ // additions go...
+ flush.flushPolyfills();
+ // flush debouncers
+ for (var i=0; i < flush._debouncers.length; i++) {
+ flush._debouncers[i].complete();
+ }
+ // clear the list of debouncers
+ if (flush._finishDebouncer) {
+ flush._finishDebouncer.complete();
+ }
+ // again make any pending CE mutations that might trigger debouncer
+ // additions go...
+ flush.flushPolyfills();
+ // flush again if there are now any debouncers to process
+ if (flush._debouncers.length && flush.guard < flush.MAX) {
+ flush.guard++;
+ flush();
+ } else {
+ flush.guard = 0;
+ }
+ };
+
+ flush.guard = 0;
+ flush.MAX = 10;
+ flush._needsTakeRecords = !Polymer.Settings.useNativeCustomElements;
+ // TODO(sorvell): There is currently not a good way
+ // to process all custom elements mutations under SD polyfill because
+ // these mutations may be inside shadowRoots.
+ flush.flushPolyfills = function() {
+ if (this._needsTakeRecords) {
+ CustomElements.takeRecords();
+ }
+ }
+ flush._debouncers = [];
+ flush._finishDebouncer;
+
+ var addDebouncer = Polymer.dom.addDebouncer = function(debouncer) {
+ flush._debouncers.push(debouncer);
+ // ensure the list of active debouncers is cleared when done.
+ flush._finishDebouncer = Polymer.Debounce(flush._finishDebouncer,
+ function() {
+ flush._debouncers = [];
+ }
+ );
+ };
function getLightChildren(node) {
var children = node._lightChildren;
View
42 src/lib/template/templatizer.html
@@ -70,20 +70,10 @@
}
},
- // Intentionally static object
- _templatizerStatic: {
- count: 0,
- callbacks: {},
- debouncer: null
- },
-
// Extension point for overrides
_instanceProps: Polymer.nob,
- created: function() {
- // id used for consolidated debouncer
- this._templatizerId = this._templatizerStatic.count++;
- },
+ _parentPropPrefix: '_parent_',
/**
* Prepares a template containing Polymer bindings by generating
@@ -162,24 +152,11 @@
},
_debounceTemplate: function(fn) {
- this._templatizerStatic.callbacks[this._templatizerId] = fn.bind(this);
- this._templatizerStatic.debouncer =
- Polymer.Debounce(this._templatizerStatic.debouncer,
- this._flushTemplates.bind(this, true));
+ Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn));
},
_flushTemplates: function(debouncerExpired) {
- var db = this._templatizerStatic.debouncer;
- // completely flush any re-queued callbacks resulting from stamping
- while (debouncerExpired || (db && db.finish)) {
- db.stop();
- var cbs = this._templatizerStatic.callbacks;
- this._templatizerStatic.callbacks = {};
- for (var id in cbs) {
- cbs[id]();
- }
- debouncerExpired = false;
- }
+ Polymer.dom.flush();
},
_customPrepEffects: function(archetype) {
@@ -236,7 +213,7 @@
// to template instances through abstract _forwardParentProp API
// that should be implemented by Templatizer users
for (prop in parentProps) {
- var parentProp = '_parent_' + prop;
+ var parentProp = this._parentPropPrefix + prop;
var effects = [{
kind: 'function',
effect: this._createForwardPropEffector(prop)
@@ -263,8 +240,9 @@
},
_createHostPropEffector: function(prop) {
+ var prefix = this._parentPropPrefix;
return function(source, value) {
- this.dataHost['_parent_' + prop] = value;
+ this.dataHost[prefix + prop] = value;
};
},
@@ -304,14 +282,14 @@
// Call extension point for Templatizer sub-classes
dataHost._forwardInstancePath.call(dataHost, this, path, value);
if (root in dataHost._parentProps) {
- dataHost.notifyPath('_parent_' + path, value);
+ dataHost.notifyPath(dataHost._parentPropPrefix + path, value);
}
},
// Overrides Base notify-path module
_pathEffector: function(path, value, fromAbove) {
if (this._forwardParentPath) {
- if (path.indexOf('_parent_') === 0) {
+ if (path.indexOf(this._parentPropPrefix) === 0) {
this._forwardParentPath(path.substring(8), value);
}
}
@@ -319,7 +297,7 @@
},
_constructorImpl: function(model, host) {
- this._rootDataHost = host._getRootDataHost();
+ this._rootDataHost = host._getRootDataHost() || host;
this._setupConfigure(model);
this._pushHost(host);
this.root = this.instanceTemplate(this._template);
@@ -391,7 +369,7 @@
model = model || {};
if (this._parentProps) {
for (var prop in this._parentProps) {
- model[prop] = this['_parent_' + prop];
+ model[prop] = this[this._parentPropPrefix + prop];
}
}
return new this.ctor(model, this);

0 comments on commit 89a767c

Please sign in to comment.
Something went wrong with that request. Please try again.