All tests pass (except one which is a todo on shark).
If `{{> foo bar}}` is to desugar into `{{#with bar}}{{> foo}}{{/with}}`, there needs to be an explicit block in the generated code in which `self.lookup("foo")` binds the correct data context (`bar`). So we now generate a UI.With rather than trying to call it from Spacebars.include. This simplifies Spacebars.include, which is nice.
Define `lookupTemplate` because `self.lookup(.., {template: true})` pretty-prints bigly.
* Use isolateValue around `foo` in `{{> foo}}` as well as `{{#foo}}` (i.e. whether or not there's a content block)
* Make UI.With always embox its argument; this is achieved by moving embox/isolateValue from Spacebars into UI. As a side effected, all reactive closures now use isolateValue, so we avoid re-rendering in a few more cases.
* Avoid calling data argument of `{{#with someHelper}}` twice ever instead of once ever (when helper isn't invalidated)
We now look for a helper named 'foo' (which can return
a dynamically chosen template object) before looking
for a global template named 'foo'. This is consistent
with the principle that adding a helper should generally
override other things with the same name (ie data properties)
This change was motivated by frontpage, which had both
a template and a helper named 'body'.
Allow server uses of LocalCollection to prefer _UnyieldingQueue. This
will mean that, as long as their observeChanges callbacks do not yield,
calls to insert/update/remove will not yield either.
- move _makeNonreactive into wrapTransform
- Use EJSON.equals for _id comparison
- Return null for nonexistent transforms
- Use isPlainObject for objectness check
- Add unit tests; remove some end-to-end tests
Also, add an EJSON.clone to the recently backported observeHandle._fetch
So, in HTML, the following are equivalent, and both mean that a checkbox is checked, because the `checked` attribute is present:
- `<input type="checkbox" checked>`
- `<input type="checkbox" checked="">`
We can't mess with that. On the other hand, in Spacebars before this commit, the following would *also* result in the checkbox being checked, regardless of whether `foo` evaluates to null, undefined, false, or the empty string:
- `<input type="checkbox" checked={{foo}}>`
- `<input type="checkbox" checked="{{foo}}">`
With this commit, the checkbox will NOT be checked if `foo` evaluates to null, undefined, or false.
To achieve this:
- In HTMLjs, an attribute is considered absent if its value is "nully" after being fully evaluated (i.e. after expanding functions and components via HTML.evaluateDynamicAttributes / HTML.evaluate). A nully value is one consisting of null, undefined, an empty array, or an array of those things. `false` is not nully and renders as "false". An empty string is not nully, and will "prop open" an attribute that would otherwise collapse into absence.
- Spacebars.mustache converts null, undefined, and false to null. So if you use {{foo}} anywhere in a template and foo evaluates to "false", that gets to converted to a null in HTMLjs (which is ignored). (true is rendered as "true".)
- When parsing HTML, an attribute that consists of *no tokens* becomes an empty string in the HTMLjs, which props open the attribute (unlike null or an empty array). (Since comment tokens are stripped during tokenization, if there are only comments in an attribute value that counts as no tokens.)
We were weirdly ignoring helpers that were falsy constants, so in `Template.main.foo = 0` / `{{foo}}` you'd get nothing, while if you did `Template.main.foo = function () { return 0; }` you would get "0".