The in-browser templating engine receives an html document with template elements in it, also inculding a data block script element with additional information on how to use those templates. The data block is called the templating program, and running it goes as follows.
Overall working
The program is a JSON array on top level. Engine has to iterate over all its top level members. One type of members is the Substitution Instruction object, the other is Instantiation Instruction, which is also a JSON object type.
- Iterate on all members of the templating program.
- Have a stack machine execute the calculate programs that it encounters.
- Its result may end up in vector (objects, arrays) or scalar (string etc.)
- On vector result, instantiate the template in question.
- On scalar result, replace the content of the text node that the xpath points to.
- When entering the sub programs, first create a scope for it and do the same thing.
Individual Templates
Engine needs to do the following steps when it instantiates a template html element.
- Enter scope (add fields of the object at the iterator, potentially hiding names that were already in scope; make it possible to restore the outer scope);
- clone template content;
- remove inline scripts (when in a component, such a script element holds the templating program; it's anyway a vulnerability, so remove them all);
- find the relevant rules in the templating program data block; apply them to the cloned fragment;
- for observable values that appeared in the calculate programs, subscribe a callback that triggers recalculation; The XPaths from the program are not usable once the fragment is in the real DOM, therefore callbacks need to keep a reference to the cloned Node objects;
- ID translation: to each element with an ID found in the template content, find and assign IDs that are unique in the outer document, not just the shadow DOM (Do we need these IDs at all?);
- insert the resulting fragment just before the template element.
XPath evaluation
document.evaluate won't work on template contents, so use new XPathEvaluator() on instantiation. When encountering Observables, XPaths are not applicable in the DOM: in the callback registered to onSet, engine needs to use the Node reference.
If a "context" field refers to the template element's ID, it means that the root of the document fragment in a template.