feat(compiler): initial version of the compiler.

Supports:
- binds text nodes, element properties and directive properties
- locates decorator, component and template directives.
- inline templates of components

The compiler is built using a pipeline design,
see core/src/compiler/pipeline package.

Integration tests to show how the compiler, change_detection and DI work
together:
core/test/compiler/integration_spec.js
This commit is contained in:
Tobias Bosch
2014-11-11 17:33:47 -08:00
parent 62efb56b0a
commit 7a70f8f92d
53 changed files with 2877 additions and 386 deletions

View File

@ -5,6 +5,7 @@ export 'dart:core' show Map, List, Set;
class MapWrapper {
static HashMap create() => new HashMap();
static HashMap createFromStringMap(m) => m;
static HashMap createFromPairs(List pairs) {
return pairs.fold({}, (m, p){
m[p[0]] = p[1];
@ -31,6 +32,12 @@ class StringMapWrapper {
static set(map, key, value) {
map[key] = value;
}
static forEach(m, fn) {
m.forEach((k,v) => fn(v,k));
}
static isEmpty(m) {
return m.isEmpty;
}
}
class ListWrapper {

View File

@ -6,6 +6,13 @@ export var Set = window.Set;
export class MapWrapper {
static create():Map { return new Map(); }
static createFromStringMap(stringMap):Map {
var result = MapWrapper.create();
for (var prop in stringMap) {
MapWrapper.set(result, prop, stringMap[prop]);
}
return result;
}
static createFromPairs(pairs:List):Map {return new Map(pairs);}
static get(m, k) { return m.get(k); }
static set(m, k, v) { m.set(k,v); }
@ -30,6 +37,17 @@ export class StringMapWrapper {
static set(map, key, value) {
map[key] = value;
}
static isEmpty(map) {
for (var prop in map) {
return false;
}
return true;
}
static forEach(map, callback) {
for (var prop in map) {
callback(map[prop], prop);
}
}
}
export class ListWrapper {
@ -67,7 +85,7 @@ export class ListWrapper {
}
static reduce(list:List, fn:Function, init) {
return list.reduce(fn, init);
}
}
static filter(array, pred:Function) {
return array.filter(pred);
}

View File

@ -5,6 +5,14 @@ import 'dart:js' show JsObject;
export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text;
// TODO(tbosch): Is there a builtin one? Why is Dart
// removing unknown elements by default?
class IdentitySanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
final identitySanitizer = new IdentitySanitizer();
class DOM {
static query(selector) {
return document.querySelector(selector);
@ -18,21 +26,30 @@ class DOM {
static getInnerHTML(el) {
return el.innerHtml;
}
static getOuterHTML(el) {
return el.outerHtml;
}
static setInnerHTML(el, value) {
el.innerHtml = value;
}
static Node firstChild(el) {
return el.firstChild;
}
static Element parentElement(el) {
return el.parent;
}
static List<Node> childNodes(el) {
return el.childNodes;
}
static appendChild(el, node) {
el.append(node);
}
static setText(Text text, String value) {
text.text = value;
}
static createTemplate(html) {
var t = document.createElement('template');
t.setInnerHtml(html);
var t = new TemplateElement();
t.setInnerHtml(html, treeSanitizer:identitySanitizer);
return t;
}
static clone(Node node) {
@ -41,10 +58,25 @@ class DOM {
static setProperty(Element element, String name, value) {
new JsObject.fromBrowserObject(element)[name] = value;
}
static getProperty(Element element, String name) {
return new JsObject.fromBrowserObject(element)[name];
}
static getElementsByClassName(Element element, String name) {
return element.getElementsByClassName(name);
}
static getElementsByTagName(Element element, String name) {
return element.querySelectorAll(name);
}
static List classList(Element element) {
return element.classes.toList();
}
static addClass(Element element, classname) {
element.classes.add(classname);
}
static hasClass(Element element, classname) {
return element.classes.contains(classname);
}
static attributeMap(Element element) {
return element.attributes;
}
}

View File

@ -4,7 +4,7 @@ export var NodeList = window.NodeList;
export var Text = window.Text;
export var Element = window.HTMLElement;
export var TemplateElement = window.HTMLTemplateElement;
import {List} from 'facade/collection';
import {List, MapWrapper} from 'facade/collection';
export class DOM {
static query(selector) {
@ -19,12 +19,21 @@ export class DOM {
static getInnerHTML(el) {
return el.innerHTML;
}
static getOuterHTML(el) {
return el.outerHTML;
}
static firstChild(el):Node {
return el.firstChild;
}
static parentElement(el) {
return el.parentElement;
}
static childNodes(el):NodeList {
return el.childNodes;
}
static appendChild(el, node) {
el.appendChild(node);
}
static setInnerHTML(el, value) {
el.innerHTML = value;
}
@ -42,10 +51,32 @@ export class DOM {
static setProperty(element:Element, name:string, value) {
element[name] = value;
}
static getProperty(element:Element, name:string) {
return element[name];
}
static getElementsByClassName(element:Element, name:string) {
return element.getElementsByClassName(name);
}
static getElementsByTagName(element:Element, name:string) {
return element.getElementsByTagName(name);
}
static classList(element:Element):List {
return Array.prototype.slice.call(element.classList, 0);
}
static addClass(element:Element, classname:string) {
element.classList.add(classname);
}
static hasClass(element:Element, classname:string) {
return element.classList.contains(classname);
}
static attributeMap(element:Element) {
var res = MapWrapper.create();
var elAttrs = element.attributes;
for (var i = 0; i < elAttrs.length; i++) {
var attrib = elAttrs[i];
MapWrapper.set(res, attrib.name, attrib.value);
}
return res;
}
}

View File

@ -58,6 +58,24 @@ class StringWrapper {
static charCodeAt(String s, int index) {
return s.codeUnitAt(index);
}
static split(String s, RegExp regExp) {
var parts = [];
var lastEnd = 0;
regExp.allMatches(s).forEach((match) {
parts.add(s.substring(lastEnd, match.start));
lastEnd = match.end;
for (var i=0; i<match.groupCount; i++) {
parts.add(match.group(i+1));
}
});
parts.add(s.substring(lastEnd));
return parts;
}
static equals(String s, String s2) {
return s == s2;
}
}
class StringJoiner {
@ -93,6 +111,9 @@ class RegExpWrapper {
static RegExp create(regExpStr) {
return new RegExp(regExpStr);
}
static firstMatch(regExp, input) {
return regExp.firstMatch(input);
}
static matcher(regExp, input) {
return regExp.allMatches(input).iterator;
}

View File

@ -1,3 +1,5 @@
import {assert} from 'rtts_assert/rtts_assert';
export var Type = Function;
export var Math = window.Math;
@ -52,6 +54,14 @@ export class StringWrapper {
static charCodeAt(s:string, index:int) {
return s.charCodeAt(index);
}
static split(s:string, regExp:RegExp) {
return s.split(regExp.multiple);
}
static equals(s:string, s2:string) {
return s === s2;
}
}
export class StringJoiner {
@ -125,15 +135,26 @@ int.assert = function(value) {
return value == null || typeof value == 'number' && value === Math.floor(value);
}
export var RegExp = window.RegExp;
export var RegExp = assert.define('RegExp', function(obj) {
assert(obj).is(assert.structure({
single: window.RegExp,
multiple: window.RegExp
}));
});
export class RegExpWrapper {
static create(regExpStr):RegExp {
return new RegExp(regExpStr, 'g');
return {
multiple: new window.RegExp(regExpStr, 'g'),
single: new window.RegExp(regExpStr)
};
}
static firstMatch(regExp, input) {
return input.match(regExp.single);
}
static matcher(regExp, input) {
return {
re: regExp,
re: regExp.multiple,
input: input
};
}