refactor(view): remove hostActions

BREAKING CHANGE

Closes #3396

Replacement. Either direct DOM access or Renderer in WebWorkers.
This commit is contained in:
Misko Hevery 2015-08-26 13:55:53 -07:00
parent 37b042b361
commit ac3f5106e4
14 changed files with 13 additions and 185 deletions

View File

@ -214,12 +214,6 @@ export class DirectiveBinding extends ResolvedBinding {
return isPresent(this.metadata) && isPresent(this.metadata.events) ? this.metadata.events : []; return isPresent(this.metadata) && isPresent(this.metadata.events) ? this.metadata.events : [];
} }
get hostActions(): Map<string, string> {
return isPresent(this.metadata) && isPresent(this.metadata.hostActions) ?
this.metadata.hostActions :
new Map();
}
get changeDetection() { return this.metadata.changeDetection; } get changeDetection() { return this.metadata.changeDetection; }
static createFromBinding(binding: Binding, ann: DirectiveMetadata): DirectiveBinding { static createFromBinding(binding: Binding, ann: DirectiveMetadata): DirectiveBinding {
@ -312,22 +306,10 @@ function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterA
}); });
} }
function _createHostActionAccessors(bwv: BindingWithVisibility): HostActionAccessor[] {
var binding = bwv.binding;
if (!(binding instanceof DirectiveBinding)) return [];
var res = [];
var db = <DirectiveBinding>binding;
MapWrapper.forEach(db.hostActions, (actionExpression, actionName) => {
res.push(new HostActionAccessor(actionExpression, reflector.getter(actionName)));
});
return res;
}
export class ProtoElementInjector { export class ProtoElementInjector {
view: viewModule.AppView; view: viewModule.AppView;
attributes: Map<string, string>; attributes: Map<string, string>;
eventEmitterAccessors: List<List<EventEmitterAccessor>>; eventEmitterAccessors: List<List<EventEmitterAccessor>>;
hostActionAccessors: List<List<HostActionAccessor>>;
protoInjector: ProtoInjector; protoInjector: ProtoInjector;
static create(parent: ProtoElementInjector, index: number, bindings: List<ResolvedBinding>, static create(parent: ProtoElementInjector, index: number, bindings: List<ResolvedBinding>,
@ -386,15 +368,10 @@ export class ProtoElementInjector {
public _firstBindingIsComponent: boolean, public _firstBindingIsComponent: boolean,
public directiveVariableBindings: Map<string, number>) { public directiveVariableBindings: Map<string, number>) {
var length = bwv.length; var length = bwv.length;
this.protoInjector = new ProtoInjector(bwv); this.protoInjector = new ProtoInjector(bwv);
this.eventEmitterAccessors = ListWrapper.createFixedSize(length); this.eventEmitterAccessors = ListWrapper.createFixedSize(length);
this.hostActionAccessors = ListWrapper.createFixedSize(length);
for (var i = 0; i < length; ++i) { for (var i = 0; i < length; ++i) {
this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]); this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]);
this.hostActionAccessors[i] = _createHostActionAccessors(bwv[i]);
} }
} }
@ -563,10 +540,6 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
return this._proto.eventEmitterAccessors; return this._proto.eventEmitterAccessors;
} }
getHostActionAccessors(): List<List<HostActionAccessor>> {
return this._proto.hostActionAccessors;
}
getDirectiveVariableBindings(): Map<string, number> { getDirectiveVariableBindings(): Map<string, number> {
return this._proto.directiveVariableBindings; return this._proto.directiveVariableBindings;
} }

View File

@ -211,7 +211,6 @@ export class AppViewManagerUtils {
currView.preBuiltObjects[boundElementIndex]); currView.preBuiltObjects[boundElementIndex]);
this._populateViewLocals(currView, elementInjector, boundElementIndex); this._populateViewLocals(currView, elementInjector, boundElementIndex);
this._setUpEventEmitters(currView, elementInjector, boundElementIndex); this._setUpEventEmitters(currView, elementInjector, boundElementIndex);
this._setUpHostActions(currView, elementInjector, boundElementIndex);
} }
} }
var pipes = isPresent(hostElementInjector) ? var pipes = isPresent(hostElementInjector) ?
@ -250,20 +249,6 @@ export class AppViewManagerUtils {
} }
} }
_setUpHostActions(view: viewModule.AppView, elementInjector: eli.ElementInjector,
boundElementIndex: number) {
var hostActions = elementInjector.getHostActionAccessors();
for (var directiveIndex = 0; directiveIndex < hostActions.length; ++directiveIndex) {
var directiveHostActions = hostActions[directiveIndex];
var directive = elementInjector.getDirectiveAtIndex(directiveIndex);
for (var index = 0; index < directiveHostActions.length; ++index) {
var hostActionAccessor = directiveHostActions[index];
hostActionAccessor.subscribe(view, boundElementIndex, directive);
}
}
}
dehydrateView(initView: viewModule.AppView) { dehydrateView(initView: viewModule.AppView) {
var endViewOffset = initView.viewOffset + var endViewOffset = initView.viewOffset +
initView.mainMergeMapping.nestedViewCountByViewIndex[initView.viewOffset]; initView.mainMergeMapping.nestedViewCountByViewIndex[initView.viewOffset];

View File

@ -628,31 +628,6 @@ export class DirectiveMetadata extends InjectableMetadata {
* In this example using `my-button` directive (ex.: `<div my-button></div>`) on a host element * In this example using `my-button` directive (ex.: `<div my-button></div>`) on a host element
* (here: `<div>` ) will ensure that this element will get the "button" role. * (here: `<div>` ) will ensure that this element will get the "button" role.
* *
* ## Actions
*
* Specifies which DOM methods a directive can invoke.
*
* ## Syntax
*
* ```
* @Directive({
* selector: 'input',
* host: {
* '@emitFocus': 'focus()'
* }
* })
* class InputDirective {
* constructor() {
* this.emitFocus = new EventEmitter();
* }
*
* focus() {
* this.emitFocus.next();
* }
* }
* ```
*
* In this example calling focus on InputDirective will result in calling focus on the input.
*/ */
host: StringMap<string, string>; host: StringMap<string, string>;

View File

@ -163,15 +163,13 @@ export class RenderDirectiveMetadata {
hostListeners: Map<string, string>; hostListeners: Map<string, string>;
hostProperties: Map<string, string>; hostProperties: Map<string, string>;
hostAttributes: Map<string, string>; hostAttributes: Map<string, string>;
hostActions: Map<string, string>;
// group 1: "property" from "[property]" // group 1: "property" from "[property]"
// group 2: "event" from "(event)" // group 2: "event" from "(event)"
// group 3: "action" from "@action" private static _hostRegExp = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
private static _hostRegExp = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\))|(?:@(.+)))$/g;
constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes, constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes,
hostActions, properties, readAttributes, type, callOnDestroy, callOnChange, properties, readAttributes, type, callOnDestroy, callOnChange, callOnCheck,
callOnCheck, callOnInit, callOnAllChangesDone, changeDetection, exportAs}: { callOnInit, callOnAllChangesDone, changeDetection, exportAs}: {
id?: string, id?: string,
selector?: string, selector?: string,
compileChildren?: boolean, compileChildren?: boolean,
@ -179,7 +177,6 @@ export class RenderDirectiveMetadata {
hostListeners?: Map<string, string>, hostListeners?: Map<string, string>,
hostProperties?: Map<string, string>, hostProperties?: Map<string, string>,
hostAttributes?: Map<string, string>, hostAttributes?: Map<string, string>,
hostActions?: Map<string, string>,
properties?: List<string>, properties?: List<string>,
readAttributes?: List<string>, readAttributes?: List<string>,
type?: number, type?: number,
@ -198,7 +195,6 @@ export class RenderDirectiveMetadata {
this.hostListeners = hostListeners; this.hostListeners = hostListeners;
this.hostAttributes = hostAttributes; this.hostAttributes = hostAttributes;
this.hostProperties = hostProperties; this.hostProperties = hostProperties;
this.hostActions = hostActions;
this.properties = properties; this.properties = properties;
this.readAttributes = readAttributes; this.readAttributes = readAttributes;
this.type = type; this.type = type;
@ -233,7 +229,6 @@ export class RenderDirectiveMetadata {
let hostListeners = new Map(); let hostListeners = new Map();
let hostProperties = new Map(); let hostProperties = new Map();
let hostAttributes = new Map(); let hostAttributes = new Map();
let hostActions = new Map();
if (isPresent(host)) { if (isPresent(host)) {
MapWrapper.forEach(host, (value: string, key: string) => { MapWrapper.forEach(host, (value: string, key: string) => {
@ -244,8 +239,6 @@ export class RenderDirectiveMetadata {
hostProperties.set(matches[1], value); hostProperties.set(matches[1], value);
} else if (isPresent(matches[2])) { } else if (isPresent(matches[2])) {
hostListeners.set(matches[2], value); hostListeners.set(matches[2], value);
} else if (isPresent(matches[3])) {
hostActions.set(matches[3], value);
} }
}); });
} }
@ -258,7 +251,6 @@ export class RenderDirectiveMetadata {
hostListeners: hostListeners, hostListeners: hostListeners,
hostProperties: hostProperties, hostProperties: hostProperties,
hostAttributes: hostAttributes, hostAttributes: hostAttributes,
hostActions: hostActions,
properties: properties, properties: properties,
readAttributes: readAttributes, readAttributes: readAttributes,
type: type, type: type,

View File

@ -380,7 +380,6 @@ export class Serializer {
'exportAs': meta.exportAs, 'exportAs': meta.exportAs,
'hostProperties': this.mapToObject(meta.hostProperties), 'hostProperties': this.mapToObject(meta.hostProperties),
'hostListeners': this.mapToObject(meta.hostListeners), 'hostListeners': this.mapToObject(meta.hostListeners),
'hostActions': this.mapToObject(meta.hostActions),
'hostAttributes': this.mapToObject(meta.hostAttributes) 'hostAttributes': this.mapToObject(meta.hostAttributes)
}; };
return obj; return obj;
@ -392,7 +391,6 @@ export class Serializer {
compileChildren: obj['compileChildren'], compileChildren: obj['compileChildren'],
hostProperties: this.objectToMap(obj['hostProperties']), hostProperties: this.objectToMap(obj['hostProperties']),
hostListeners: this.objectToMap(obj['hostListeners']), hostListeners: this.objectToMap(obj['hostListeners']),
hostActions: this.objectToMap(obj['hostActions']),
hostAttributes: this.objectToMap(obj['hostAttributes']), hostAttributes: this.objectToMap(obj['hostAttributes']),
properties: obj['properties'], properties: obj['properties'],
readAttributes: obj['readAttributes'], readAttributes: obj['readAttributes'],

View File

@ -117,11 +117,6 @@ class HasEventEmitter {
constructor() { this.emitter = "emitter"; } constructor() { this.emitter = "emitter"; }
} }
class HasHostAction {
hostActionName;
constructor() { this.hostActionName = "hostAction"; }
}
class NeedsAttribute { class NeedsAttribute {
typeAttribute; typeAttribute;
titleAttribute; titleAttribute;
@ -433,18 +428,6 @@ export function main() {
expect(accessor.eventName).toEqual('publicEmitter'); expect(accessor.eventName).toEqual('publicEmitter');
expect(accessor.getter(new HasEventEmitter())).toEqual('emitter'); expect(accessor.getter(new HasEventEmitter())).toEqual('emitter');
}); });
it('should return a list of hostAction accessors', () => {
var binding = DirectiveBinding.createFromType(
HasEventEmitter, new DirectiveMetadata({host: {'@hostActionName': 'onAction'}}));
var inj = createPei(null, 0, [binding]);
expect(inj.hostActionAccessors.length).toEqual(1);
var accessor = inj.hostActionAccessors[0][0];
expect(accessor.methodName).toEqual('onAction');
expect(accessor.getter(new HasHostAction())).toEqual('hostAction');
});
}); });
describe(".create", () => { describe(".create", () => {

View File

@ -841,31 +841,6 @@ export function main() {
}); });
})); }));
if (DOM.supportsDOMEvents()) {
it("should support invoking methods on the host element via hostActions",
inject(
[TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<div update-host-actions></div>',
directives: [DirectiveUpdatingHostActions]
}))
.createAsync(MyComp)
.then((rootTC) => {
var tc = rootTC.componentViewChildren[0];
var nativeElement = tc.nativeElement;
var updateHost = tc.inject(DirectiveUpdatingHostActions);
ObservableWrapper.subscribe(updateHost.setAttr, (_) => {
expect(DOM.hasAttribute(nativeElement, 'update-host-actions')).toBe(true);
async.done();
});
updateHost.triggerSetAttr('value');
});
}));
}
it('should support render events', it('should support render events',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView( tcb.overrideView(

View File

@ -87,17 +87,13 @@ export function main() {
createHostPv([createNestedElBinder(createComponentPv()), createEmptyElBinder()]); createHostPv([createNestedElBinder(createComponentPv()), createEmptyElBinder()]);
var hostView = createViewWithChildren(hostPv); var hostView = createViewWithChildren(hostPv);
var spyEventAccessor1 = SpyObject.stub({"subscribe": null}); var spyEventAccessor1 = SpyObject.stub({"subscribe": null});
SpyObject.stub(hostView.elementInjectors[0], { SpyObject.stub(
'getHostActionAccessors': [], hostView.elementInjectors[0],
'getEventEmitterAccessors': [[spyEventAccessor1]], {'getEventEmitterAccessors': [[spyEventAccessor1]], 'getDirectiveAtIndex': dir});
'getDirectiveAtIndex': dir
});
var spyEventAccessor2 = SpyObject.stub({"subscribe": null}); var spyEventAccessor2 = SpyObject.stub({"subscribe": null});
SpyObject.stub(hostView.elementInjectors[1], { SpyObject.stub(
'getHostActionAccessors': [], hostView.elementInjectors[1],
'getEventEmitterAccessors': [[spyEventAccessor2]], {'getEventEmitterAccessors': [[spyEventAccessor2]], 'getDirectiveAtIndex': dir});
'getDirectiveAtIndex': dir
});
utils.hydrateRootHostView(hostView, createInjector()); utils.hydrateRootHostView(hostView, createInjector());
@ -105,31 +101,6 @@ export function main() {
expect(spyEventAccessor2.spy('subscribe')).toHaveBeenCalledWith(hostView, 1, dir); expect(spyEventAccessor2.spy('subscribe')).toHaveBeenCalledWith(hostView, 1, dir);
}); });
it("should set up host action listeners", () => {
var dir = new Object();
var hostPv =
createHostPv([createNestedElBinder(createComponentPv()), createEmptyElBinder()]);
var hostView = createViewWithChildren(hostPv);
var spyActionAccessor1 = SpyObject.stub({"subscribe": null});
SpyObject.stub(hostView.elementInjectors[0], {
'getHostActionAccessors': [[spyActionAccessor1]],
'getEventEmitterAccessors': [],
'getDirectiveAtIndex': dir
});
var spyActionAccessor2 = SpyObject.stub({"subscribe": null});
SpyObject.stub(hostView.elementInjectors[1], {
'getHostActionAccessors': [[spyActionAccessor2]],
'getEventEmitterAccessors': [],
'getDirectiveAtIndex': dir
});
utils.hydrateRootHostView(hostView, createInjector());
expect(spyActionAccessor1.spy('subscribe')).toHaveBeenCalledWith(hostView, 0, dir);
expect(spyActionAccessor2.spy('subscribe')).toHaveBeenCalledWith(hostView, 1, dir);
});
it("should not hydrate element injectors of component views inside of embedded fragments", it("should not hydrate element injectors of component views inside of embedded fragments",
() => { () => {
var hostView = createViewWithChildren(createHostPv([ var hostView = createViewWithChildren(createHostPv([

View File

@ -8,17 +8,12 @@ export function main() {
describe('host', () => { describe('host', () => {
it('should parse host configuration', () => { it('should parse host configuration', () => {
var md = RenderDirectiveMetadata.create({ var md = RenderDirectiveMetadata.create({
host: MapWrapper.createFromPairs([ host: MapWrapper.createFromPairs(
['(event)', 'eventVal'], [['(event)', 'eventVal'], ['[prop]', 'propVal'], ['attr', 'attrVal']])
['[prop]', 'propVal'],
['@action', 'actionVal'],
['attr', 'attrVal']
])
}); });
expect(md.hostListeners).toEqual(MapWrapper.createFromPairs([['event', 'eventVal']])); expect(md.hostListeners).toEqual(MapWrapper.createFromPairs([['event', 'eventVal']]));
expect(md.hostProperties).toEqual(MapWrapper.createFromPairs([['prop', 'propVal']])); expect(md.hostProperties).toEqual(MapWrapper.createFromPairs([['prop', 'propVal']]));
expect(md.hostActions).toEqual(MapWrapper.createFromPairs([['action', 'actionVal']]));
expect(md.hostAttributes).toEqual(MapWrapper.createFromPairs([['attr', 'attrVal']])); expect(md.hostAttributes).toEqual(MapWrapper.createFromPairs([['attr', 'attrVal']]));
}); });
}); });

View File

@ -97,11 +97,6 @@ void allTests() {
expect(metadata.hostAttributes.length).toBe(1); expect(metadata.hostAttributes.length).toBe(1);
expect(metadata.hostAttributes).toContain('attName'); expect(metadata.hostAttributes).toContain('attName');
expect(metadata.hostAttributes['attName']).toEqual('attValue'); expect(metadata.hostAttributes['attName']).toEqual('attValue');
expect(metadata.hostActions).toBeNotNull();
expect(metadata.hostActions.length).toBe(1);
expect(metadata.hostActions).toContain('actionName');
expect(metadata.hostActions['actionName']).toEqual('actionValue');
}); });
it('should parse lifecycle events.', () async { it('should parse lifecycle events.', () async {

View File

@ -15,7 +15,6 @@ void initReflector(reflector) {
const Component(host: const { const Component(host: const {
'(change)': 'onChange(\$event)', '(change)': 'onChange(\$event)',
'[value]': 'value', '[value]': 'value',
'@actionName': 'actionValue',
'attName': 'attValue' 'attName': 'attValue'
}) })
], const [ ], const [

View File

@ -7,7 +7,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],

View File

@ -7,7 +7,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": null, "properties": null,
"readAttributes": null, "readAttributes": null,
@ -31,7 +30,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {"hprop": "hprop"}, "hostProperties": {"hprop": "hprop"},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": ["prop"], "properties": ["prop"],
"readAttributes": null, "readAttributes": null,
@ -55,7 +53,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {"subevent": "doAThing()"}, "hostListeners": {"subevent": "doAThing()"},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": null, "readAttributes": null,
@ -79,7 +76,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": ["ngForOf"], "properties": ["ngForOf"],
"readAttributes": null, "readAttributes": null,
@ -95,4 +91,4 @@
"version": 1 "version": 1
} }
} }
} }

View File

@ -7,7 +7,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": null, "properties": null,
"readAttributes": null, "readAttributes": null,
@ -31,7 +30,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -55,7 +53,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -79,7 +76,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -103,7 +99,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -127,7 +122,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -151,7 +145,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -175,7 +168,6 @@
"compileChildren": true, "compileChildren": true,
"hostProperties": {}, "hostProperties": {},
"hostListeners": {}, "hostListeners": {},
"hostActions": {},
"hostAttributes": {}, "hostAttributes": {},
"properties": [], "properties": [],
"readAttributes": [], "readAttributes": [],
@ -191,4 +183,4 @@
"version": 1 "version": 1
} }
} }
} }