feat(compiler): parse5 DOM adapter

Closes #841
This commit is contained in:
Marc Laval
2015-03-01 22:17:36 +01:00
parent 537f943f57
commit 1d4ff9bcdc
13 changed files with 647 additions and 140 deletions

View File

@ -19,10 +19,6 @@ import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
import {EventManager, DomEventsPlugin} from 'angular2/src/core/events/event_manager';
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
import {Decorator, Component, Viewport} from 'angular2/src/core/annotations/annotations';
import {Template} from 'angular2/src/core/annotations/template';
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
@ -64,7 +60,7 @@ export function main() {
ctx = new MyComp();
view = pv.instantiate(
null,
new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()),
null,
reflector
);
view.hydrate(new Injector([]), null, ctx);
@ -354,7 +350,7 @@ export function main() {
var value = view.contextWithLocals.get('alice');
expect(value).not.toBe(null);
expect(value.tagName).toEqual('DIV');
expect(value.tagName.toLowerCase()).toEqual('div');
done();
})
@ -724,18 +720,3 @@ class DecoratorListeningEvent {
this.msg = msg;
}
}
class FakeVmTurnZone extends VmTurnZone {
constructor() {
super({enableLongStackTrace: false});
}
run(fn) {
fn();
}
runOutsideAngular(fn) {
fn();
}
}

View File

@ -1,4 +1,4 @@
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el} from 'angular2/test_lib';
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, IS_NODEJS} from 'angular2/test_lib';
import {ShadowCss} from 'angular2/src/core/compiler/shadow_dom_emulation/shadow_css';
import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
@ -91,13 +91,16 @@ export function main() {
expect(StringWrapper.contains(css, '#menu > .bar {;background: blue;}')).toBeTruthy();
});
it('should support polyfill-rule', () => {
var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host');
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
if (!IS_NODEJS) {
//TODO: reactivate once CSS parser is fixed: https://github.com/reworkcss/css/issues/65
it('should support polyfill-rule', () => {
var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host');
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host');
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
});
css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host');
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
});
}
it('should handle ::shadow', () => {
var css = s('x::shadow > y {}', 'a');

View File

@ -87,7 +87,7 @@ export function main() {
strategy.attachTemplate(host, view);
var firstChild = DOM.firstChild(host);
expect(DOM.tagName(firstChild)).toEqual('DIV');
expect(DOM.tagName(firstChild).toLowerCase()).toEqual('div');
expect(firstChild).toHaveText('view');
expect(host).toHaveText('view');
});
@ -222,7 +222,7 @@ export function main() {
strategy.attachTemplate(host, view);
var firstChild = DOM.firstChild(host);
expect(DOM.tagName(firstChild)).toEqual('DIV');
expect(DOM.tagName(firstChild).toLowerCase()).toEqual('div');
expect(firstChild).toHaveText('view');
expect(host).toHaveText('view');
});

View File

@ -1,4 +1,4 @@
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el, proxy} from 'angular2/test_lib';
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el, proxy, IS_NODEJS} from 'angular2/test_lib';
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'angular2/src/core/compiler/view';
import {ProtoElementInjector, ElementInjector, DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
import {EmulatedScopedShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
@ -444,96 +444,98 @@ export function main() {
});
});
describe('event handlers', () => {
var view, ctx, called, receivedEvent, dispatchedEvent;
if (!IS_NODEJS) {
describe('event handlers', () => {
var view, ctx, called, receivedEvent, dispatchedEvent;
function createViewAndContext(protoView) {
view = createView(protoView,
new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
ctx = view.context;
called = 0;
receivedEvent = null;
ctx.callMe = (event) => {
called += 1;
receivedEvent = event;
function createViewAndContext(protoView) {
view = createView(protoView,
new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
ctx = view.context;
called = 0;
receivedEvent = null;
ctx.callMe = (event) => {
called += 1;
receivedEvent = event;
}
}
}
function dispatchClick(el) {
dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(el, dispatchedEvent);
}
function dispatchClick(el) {
dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(el, dispatchedEvent);
}
function createProtoView() {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, []));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
return pv;
}
function createProtoView() {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, []));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
return pv;
}
it('should fire on non-bubbling native events', () => {
createViewAndContext(createProtoView());
it('should fire on non-bubbling native events', () => {
createViewAndContext(createProtoView());
dispatchClick(view.nodes[0]);
dispatchClick(view.nodes[0]);
expect(called).toEqual(1);
expect(receivedEvent).toBe(dispatchedEvent);
expect(called).toEqual(1);
expect(receivedEvent).toBe(dispatchedEvent);
});
it('should not fire on a bubbled native events', () => {
createViewAndContext(createProtoView());
dispatchClick(view.nodes[0].firstChild);
// This test passes trivially on webkit browsers due to
// https://bugs.webkit.org/show_bug.cgi?id=122755
expect(called).toEqual(0);
});
it('should not throw if the view is dehydrated', () => {
createViewAndContext(createProtoView());
view.dehydrate();
expect(() => dispatchClick(view.nodes[0])).not.toThrow();
expect(called).toEqual(0);
});
it('should support custom event emitters', () => {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
createViewAndContext(pv);
var dir = view.elementInjectors[0].get(EventEmitterDirective);
var dispatchedEvent = new Object();
dir.click(dispatchedEvent);
expect(receivedEvent).toBe(dispatchedEvent);
expect(called).toEqual(1);
// Should not eval the binding, because custom emitter takes over.
dispatchClick(view.nodes[0]);
expect(called).toEqual(1);
});
it('should bind to directive events', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirectiveWithEventHandler]));
pv.bindEvent('click', parser.parseAction('onEvent($event)', null), 0);
view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
var directive = view.elementInjectors[0].get(SomeDirectiveWithEventHandler);
expect(directive.event).toEqual(null);
dispatchClick(view.nodes[0]);
expect(directive.event).toBe(dispatchedEvent);
});
});
it('should not fire on a bubbled native events', () => {
createViewAndContext(createProtoView());
dispatchClick(view.nodes[0].firstChild);
// This test passes trivially on webkit browsers due to
// https://bugs.webkit.org/show_bug.cgi?id=122755
expect(called).toEqual(0);
});
it('should not throw if the view is dehydrated', () => {
createViewAndContext(createProtoView());
view.dehydrate();
expect(() => dispatchClick(view.nodes[0])).not.toThrow();
expect(called).toEqual(0);
});
it('should support custom event emitters', () => {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
createViewAndContext(pv);
var dir = view.elementInjectors[0].get(EventEmitterDirective);
var dispatchedEvent = new Object();
dir.click(dispatchedEvent);
expect(receivedEvent).toBe(dispatchedEvent);
expect(called).toEqual(1);
// Should not eval the binding, because custom emitter takes over.
dispatchClick(view.nodes[0]);
expect(called).toEqual(1);
});
it('should bind to directive events', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirectiveWithEventHandler]));
pv.bindEvent('click', parser.parseAction('onEvent($event)', null), 0);
view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
var directive = view.elementInjectors[0].get(SomeDirectiveWithEventHandler);
expect(directive.event).toEqual(null);
dispatchClick(view.nodes[0]);
expect(directive.event).toBe(dispatchedEvent);
});
});
}
describe('react to record changes', () => {
var view, cd, ctx;