Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Implement one-time bindings.
Browse files Browse the repository at this point in the history
This patch introduces the first cut at one-time bindings. The syntax uses double-brackets as insertion syntax ('[[ foo ]]').

Note that this patch also changes the follow pre-existing semantics:

1) Prior to this patch, it was tolerated for the delegateFn returned by prepareBinding to decline to return an observable. This is no longer the case. It is now required that if prepareBinding return a fn, that the fn return the correct value type for the given binding type (dynamic vs. one time).

2) This patch fixes two bugs in template repeat semantics:

a) It is only neccesary to observe the iteratedValue if the value can in as an Array from the repeat directive.

b) Previously mutating the observed array and them immediately replacing it with another array may have resulted in errors, as the code assumed that when the iteratedValue was changed, present state of iteratedValue properly reflected the existing instances. Now the code keeps an internal array which represents the fully-synchronized state of the instances and should never be confusable.

Note: I'm aware the code which sets up the TemplateIterator with repeat/bind/if values/observed values is a mess. I'm currently taking this as an indication of a problem with the design -- which I plan to fix as a follow-on.

The root problem is that templates are currently set in motion via two different public API channels: template.model and template.bind(). I think template needs to just come to terms with being different -- it should only be set in motion with template.model.

[email protected], arv
BUG=

Review URL: https://codereview.appspot.com/38540047
  • Loading branch information
rafaelw committed Dec 18, 2013
1 parent 11595a7 commit c911c2c
Show file tree
Hide file tree
Showing 4 changed files with 689 additions and 132 deletions.
37 changes: 25 additions & 12 deletions benchmark/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,36 +81,45 @@
return elementTypes[elementTypes.next++];
}

function nextBindingText(isStatic, expression) {
function sd(oneTime) {
return oneTime ? '[[' : '{{';
}

function ed(oneTime) {
return oneTime ? ']]' : '}}';
}

function nextBindingText(isStatic, oneTime, expression) {
if (isStatic)
return 'I am Text!';

if (expression) {
return '{{ ' + getNextPropName() + ' + ' +
getNextPropName() + ' }}';
return sd(oneTime) + getNextPropName() + ' + ' +
getNextPropName() + ed(oneTime);
}

return '{{ ' + getNextPropName() + ' }}';
return sd(oneTime) + getNextPropName() + ed(oneTime);
}

function nextBinding(isStatic, compound, expression) {
function nextBinding(isStatic, oneTime, compound, expression) {
if (isStatic)
return nextBindingText(isStatic);
if (compound) {
return nextBindingText(false, expression) + ' ' +
nextBindingText(false, expression);
return nextBindingText(false, oneTime, expression) + ' ' +
nextBindingText(false, oneTime, expression);
}

return nextBindingText(false, expression);
return nextBindingText(false, oneTime, expression);
}

function MDVBenchmark(testDiv, width, depth, decoration, instanceCount,
compoundBindings, expressions) {
oneTimeBindings, compoundBindings, expressions) {
Benchmark.call(this);
this.testDiv = testDiv;
this.width = width;
this.depth = depth;
this.decoration = decoration;
this.oneTimeBindings = oneTimeBindings;
this.compoundBindings = compoundBindings;
this.expressions = expressions;

Expand Down Expand Up @@ -142,7 +151,9 @@

getBindingText: function() {
return nextBinding(this.bindingCounter++ > this.bindingCount,
this.compoundBindings, this.expressions);
this.oneTimeBindings,
this.compoundBindings,
this.expressions);
},

decorate: function(element) {
Expand Down Expand Up @@ -222,8 +233,10 @@
testDiv.innerHTML = '';
var div = document.createElement('div');
div.appendChild(this.fragment.cloneNode(true));
this.handlebarsTemplate = '{{#each this}}' + div.innerHTML + '{{/each}}';
this.compiledTemplate = Handlebars.compile(this.handlebarsTemplate);
var stringTemplate = '{{#each this}}' + div.innerHTML + '{{/each}}';
stringTemplate = stringTemplate.replace(/\[\[/g, '{{');
stringTemplate = stringTemplate.replace(/\]\]/g, '}}');
this.compiledTemplate = Handlebars.compile(stringTemplate);
},

runHandlebars: function() {
Expand Down
13 changes: 11 additions & 2 deletions benchmark/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ <h1>Template instantiation benchmarks</h1>
Handlebars: <input id="handlebarsCheckbox" type="checkbox" checked>

<button id="go">Run Benchmarks</button><br>
One-time Bindings: <input id="oneTimeBindings" type="checkbox" checked>
Compound Bindings: <input id="compoundBindings" type="checkbox">
Expressions: <input id="expressions" type="checkbox">

<span id="statusSpan"></span>

<section style="width: 100%">
Expand Down Expand Up @@ -108,6 +108,7 @@ <h3 style="margin-left: 440px">Binding Density</h3>
var handlebarsCheckbox = document.getElementById('handlebarsCheckbox');

var compoundCheckbox = document.getElementById('compoundBindings');
var oneTimeBindings = document.getElementById('oneTimeBindings');
var expressionCheckbox = document.getElementById('expressions');

var bindingDensityInput = document.getElementById('bindingDensityInput');
Expand Down Expand Up @@ -143,9 +144,16 @@ <h3 style="margin-left: 440px">Binding Density</h3>
handlebarsCheckbox.checked = false;
})

oneTimeBindings.addEventListener('click', function() {
if (!oneTimeBindings.checked)
handlebarsCheckbox.checked = false;
})

handlebarsCheckbox.addEventListener('click', function() {
if (handlebarsCheckbox.checked)
if (handlebarsCheckbox.checked) {
expressionCheckbox.checked = false;
oneTimeBindings.checked = true;
}
})

goButton.addEventListener('click', function() {
Expand Down Expand Up @@ -228,6 +236,7 @@ <h3 style="margin-left: 440px">Binding Density</h3>
var instanceCount = Number(instanceCountSelect.value);

var test = new MDVBenchmark(testDiv, width, depth, decoration, instanceCount,
oneTimeBindings.checked,
compoundBindings.checked,
expressionCheckbox.checked);
var runner = new BenchmarkRunner(test,
Expand Down
Loading

0 comments on commit c911c2c

Please sign in to comment.