parent
7e51e52f55
commit
4d62be69c5
|
@ -78,6 +78,17 @@ export {
|
|||
query as Q,
|
||||
queryRefresh as qR,
|
||||
} from './query';
|
||||
export {
|
||||
objectLiteral1 as o1,
|
||||
objectLiteral2 as o2,
|
||||
objectLiteral3 as o3,
|
||||
objectLiteral4 as o4,
|
||||
objectLiteral5 as o5,
|
||||
objectLiteral6 as o6,
|
||||
objectLiteral7 as o7,
|
||||
objectLiteral8 as o8,
|
||||
} from './object_literal';
|
||||
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -494,7 +494,8 @@ export function createTView(): TView {
|
|||
contentCheckHooks: null,
|
||||
viewHooks: null,
|
||||
viewCheckHooks: null,
|
||||
destroyHooks: null
|
||||
destroyHooks: null,
|
||||
objectLiterals: null
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1754,6 +1755,10 @@ export function getRenderer(): Renderer3 {
|
|||
return renderer;
|
||||
}
|
||||
|
||||
export function getTView(): TView {
|
||||
return currentView.tView;
|
||||
}
|
||||
|
||||
export function getDirectiveInstance<T>(instanceOrArray: T | [T]): T {
|
||||
// Directives with content queries store an array in data[directiveIndex]
|
||||
// with the instance as the first index
|
||||
|
|
|
@ -259,6 +259,9 @@ export interface TView {
|
|||
* Odd indices: Hook function
|
||||
*/
|
||||
destroyHooks: HookData|null;
|
||||
|
||||
/** Contains copies of object literals that were passed as bindings in this view. */
|
||||
objectLiterals: any[]|null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {assertEqual} from './assert';
|
||||
import {NO_CHANGE, bind, getTView} from './instructions';
|
||||
|
||||
|
||||
/**
|
||||
* Updates an expression in an object literal if the expression has changed.
|
||||
* Used in objectLiteral instructions.
|
||||
*
|
||||
* @param obj Object to update
|
||||
* @param key Key to set in object
|
||||
* @param exp Expression to set at key
|
||||
* @returns Whether or not there has been a change
|
||||
*/
|
||||
function updateBinding(obj: any, key: string | number, exp: any): boolean {
|
||||
if (bind(exp) !== NO_CHANGE) {
|
||||
obj[key] = exp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Updates two expressions in an object literal if they have changed. */
|
||||
function updateBinding2(obj: any, key1: number, exp1: any, key2: number, exp2: any): boolean {
|
||||
let different = updateBinding(obj, key1, exp1);
|
||||
return updateBinding(obj, key2, exp2) || different;
|
||||
}
|
||||
|
||||
/** Updates four expressions in an object literal if they have changed. */
|
||||
function updateBinding4(
|
||||
obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number, exp3: any,
|
||||
key4: number, exp4: any): boolean {
|
||||
let different = updateBinding2(obj, key1, exp1, key2, exp2);
|
||||
return updateBinding2(obj, key3, exp3, key4, exp4) || different;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a blueprint of an object or array if one has already been saved, or copies the
|
||||
* object and saves it for the next change detection run if it hasn't.
|
||||
*/
|
||||
function getMutableBlueprint(index: number, obj: any): any {
|
||||
const tView = getTView();
|
||||
const objectLiterals = tView.objectLiterals;
|
||||
if (objectLiterals && index < objectLiterals.length) {
|
||||
return objectLiterals[index];
|
||||
} else {
|
||||
ngDevMode && objectLiterals && assertEqual(index, objectLiterals.length, 'index');
|
||||
return (objectLiterals || (tView.objectLiterals = []))[index] = copyObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/** Copies an object or array */
|
||||
function copyObject(obj: any): any {
|
||||
return Array.isArray(obj) ? obj.slice() : {...obj};
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expression in the given object if it has changed and returns a copy of the object.
|
||||
* Or if the expression hasn't changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex Index of object blueprint in objectLiterals
|
||||
* @param obj Object to update
|
||||
* @param key Key to set in object
|
||||
* @param exp Expression to set at key
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral1(objIndex: number, obj: any, key: string | number, exp: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
if (bind(exp) === NO_CHANGE) {
|
||||
return NO_CHANGE;
|
||||
} else {
|
||||
obj[key] = exp;
|
||||
// Must copy to change identity when binding changes
|
||||
return copyObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @returns A copy of the array or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral2(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
return updateBinding2(obj, key1, exp1, key2, exp2) ? copyObject(obj) : NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral3(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
let different = updateBinding2(obj, key1, exp1, key2, exp2);
|
||||
return updateBinding(obj, key3, exp3) || different ? copyObject(obj) : NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @param key4
|
||||
* @param exp4
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral4(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any, key4: number, exp4: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
return updateBinding4(obj, key1, exp1, key2, exp2, key3, exp3, key4, exp4) ? copyObject(obj) :
|
||||
NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @param key4
|
||||
* @param exp4
|
||||
* @param key5
|
||||
* @param exp5
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral5(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any, key4: number, exp4: any, key5: number, exp5: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
let different = updateBinding4(obj, key1, exp1, key2, exp2, key3, exp3, key4, exp4);
|
||||
return updateBinding(obj, key5, exp5) || different ? copyObject(obj) : NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @param key4
|
||||
* @param exp4
|
||||
* @param key5
|
||||
* @param exp5
|
||||
* @param key6
|
||||
* @param exp6
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral6(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any, key4: number, exp4: any, key5: number, exp5: any, key6: number, exp6: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
let different = updateBinding4(obj, key1, exp1, key2, exp2, key3, exp3, key4, exp4);
|
||||
return updateBinding2(obj, key5, exp5, key6, exp6) || different ? copyObject(obj) : NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @param key4
|
||||
* @param exp4
|
||||
* @param key5
|
||||
* @param exp5
|
||||
* @param key6
|
||||
* @param exp6
|
||||
* @param key7
|
||||
* @param exp7
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral7(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any, key4: number, exp4: any, key5: number, exp5: any, key6: number, exp6: any,
|
||||
key7: number, exp7: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
let different = updateBinding4(obj, key1, exp1, key2, exp2, key3, exp3, key4, exp4);
|
||||
different = updateBinding2(obj, key5, exp5, key6, exp6) || different;
|
||||
return updateBinding(obj, key7, exp7) || different ? copyObject(obj) : NO_CHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the expressions in the given object if they have changed and returns a copy of the
|
||||
* object.
|
||||
* Or if no expressions have changed, returns NO_CHANGE.
|
||||
*
|
||||
* @param objIndex
|
||||
* @param obj
|
||||
* @param key1
|
||||
* @param exp1
|
||||
* @param key2
|
||||
* @param exp2
|
||||
* @param key3
|
||||
* @param exp3
|
||||
* @param key4
|
||||
* @param exp4
|
||||
* @param key5
|
||||
* @param exp5
|
||||
* @param key6
|
||||
* @param exp6
|
||||
* @param key7
|
||||
* @param exp7
|
||||
* @param key8
|
||||
* @param exp8
|
||||
* @returns A copy of the object or NO_CHANGE
|
||||
*/
|
||||
export function objectLiteral8(
|
||||
objIndex: number, obj: any, key1: number, exp1: any, key2: number, exp2: any, key3: number,
|
||||
exp3: any, key4: number, exp4: any, key5: number, exp5: any, key6: number, exp6: any,
|
||||
key7: number, exp7: any, key8: number, exp8: any): any {
|
||||
obj = getMutableBlueprint(objIndex, obj);
|
||||
let different = updateBinding4(obj, key1, exp1, key2, exp2, key3, exp3, key4, exp4);
|
||||
return updateBinding4(obj, key5, exp5, key6, exp6, key7, exp7, key8, exp8) || different ?
|
||||
copyObject(obj) :
|
||||
NO_CHANGE;
|
||||
}
|
|
@ -173,6 +173,76 @@ describe('compiler specification', () => {
|
|||
expect(log).toEqual(['ChildComponent', 'SomeDirective']);
|
||||
});
|
||||
|
||||
describe('memoization', () => {
|
||||
@Component({
|
||||
selector: 'my-comp',
|
||||
template: `
|
||||
<p>{{ names[0] }}</p>
|
||||
<p>{{ names[1] }}</p>
|
||||
`
|
||||
})
|
||||
class MyComp {
|
||||
@Input() names: string[];
|
||||
|
||||
static ngComponentDef = r3.defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
factory: function MyComp_Factory() { return new MyComp(); },
|
||||
template: function MyComp_Template(ctx: MyComp, cm: boolean) {
|
||||
if (cm) {
|
||||
r3.E(0, 'p');
|
||||
r3.T(1);
|
||||
r3.e();
|
||||
r3.E(2, 'p');
|
||||
r3.T(3);
|
||||
r3.e();
|
||||
}
|
||||
r3.t(1, r3.b(ctx.names[0]));
|
||||
r3.t(3, r3.b(ctx.names[1]));
|
||||
},
|
||||
inputs: {names: 'names'}
|
||||
});
|
||||
}
|
||||
|
||||
it('should memoize array literals', () => {
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<my-comp [names]="['Nancy', customName]"></my-comp>
|
||||
`
|
||||
})
|
||||
class MyApp {
|
||||
customName = 'Bess';
|
||||
|
||||
// NORMATIVE
|
||||
static ngComponentDef = r3.defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: MyApp, cm: boolean) {
|
||||
if (cm) {
|
||||
r3.E(0, MyComp);
|
||||
r3.e();
|
||||
}
|
||||
r3.p(0, 'names', r3.o1(0, e0_literal, 1, ctx.customName));
|
||||
MyComp.ngComponentDef.h(1, 0);
|
||||
r3.r(1, 0);
|
||||
}
|
||||
});
|
||||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NORMATIVE
|
||||
const e0_literal = ['Nancy', null];
|
||||
// /NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-comp><p>Nancy</p><p>Bess</p></my-comp>`);
|
||||
expect(e0_literal).toEqual(['Nancy', null]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should support content projection', () => {
|
||||
@Component({selector: 'simple', template: `<div><ng-content></ng-content></div>`})
|
||||
class SimpleComponent {
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {E, defineComponent, e, m, o1, o2, o3, o4, o5, o6, o7, o8, p, r} from '../../src/render3/index';
|
||||
import {renderToHtml} from '../../test/render3/render_util';
|
||||
|
||||
describe('array literals', () => {
|
||||
let myComp: MyComp;
|
||||
|
||||
class MyComp {
|
||||
names: string[];
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
factory: function MyComp_Factory() { return myComp = new MyComp(); },
|
||||
template: function MyComp_Template(ctx: MyComp, cm: boolean) {},
|
||||
inputs: {names: 'names'}
|
||||
});
|
||||
}
|
||||
|
||||
it('should support an array literal with a binding', () => {
|
||||
/** <my-comp [names]="['Nancy', customName, 'Bess']"></my-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, MyComp);
|
||||
e();
|
||||
}
|
||||
p(0, 'names', o1(0, e0_literal, 1, ctx.customName));
|
||||
MyComp.ngComponentDef.h(1, 0);
|
||||
r(1, 0);
|
||||
}
|
||||
|
||||
const e0_literal = ['Nancy', null, 'Bess'];
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson'});
|
||||
const firstArray = myComp !.names;
|
||||
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess']);
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson'});
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']);
|
||||
expect(firstArray).toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'Hannah'});
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Hannah', 'Bess']);
|
||||
|
||||
// Identity must change if binding changes
|
||||
expect(firstArray).not.toBe(myComp !.names);
|
||||
|
||||
expect(e0_literal).toEqual(['Nancy', null, 'Bess']);
|
||||
});
|
||||
|
||||
it('should support multiple array literals passed through to one node', () => {
|
||||
let manyPropComp: ManyPropComp;
|
||||
|
||||
class ManyPropComp {
|
||||
names1: string[];
|
||||
names2: string[];
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ManyPropComp,
|
||||
tag: 'many-prop-comp',
|
||||
factory: function ManyPropComp_Factory() { return manyPropComp = new ManyPropComp(); },
|
||||
template: function ManyPropComp_Template(ctx: ManyPropComp, cm: boolean) {},
|
||||
inputs: {names1: 'names1', names2: 'names2'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <many-prop-comp [names1]="['Nancy', customName]" [names2]="[customName2]"></many-prop-comp>
|
||||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, ManyPropComp);
|
||||
e();
|
||||
}
|
||||
p(0, 'names1', o1(0, e0_literal, 1, ctx.customName));
|
||||
p(0, 'names2', o1(1, e0_literal_1, 0, ctx.customName2));
|
||||
ManyPropComp.ngComponentDef.h(1, 0);
|
||||
r(1, 0);
|
||||
}
|
||||
|
||||
const e0_literal = ['Nancy', null];
|
||||
const e0_literal_1 = [null];
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'George'});
|
||||
expect(manyPropComp !.names1).toEqual(['Nancy', 'Carson']);
|
||||
expect(manyPropComp !.names2).toEqual(['George']);
|
||||
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Carson'});
|
||||
expect(manyPropComp !.names1).toEqual(['Nancy', 'George']);
|
||||
expect(manyPropComp !.names2).toEqual(['Carson']);
|
||||
|
||||
expect(e0_literal).toEqual(['Nancy', null]);
|
||||
expect(e0_literal_1).toEqual([null]);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should support an array literal with more than 1 binding', () => {
|
||||
/** <my-comp [names]="['Nancy', customName, 'Bess', customName2]"></my-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, MyComp);
|
||||
e();
|
||||
}
|
||||
p(0, 'names', o2(0, e0_literal, 1, ctx.customName, 3, ctx.customName2));
|
||||
MyComp.ngComponentDef.h(1, 0);
|
||||
r(1, 0);
|
||||
}
|
||||
|
||||
const e0_literal = ['Nancy', null, 'Bess', null];
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'});
|
||||
const firstArray = myComp !.names;
|
||||
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'});
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
|
||||
expect(firstArray).toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Hannah'});
|
||||
expect(myComp !.names).toEqual(['Nancy', 'George', 'Bess', 'Hannah']);
|
||||
expect(firstArray).not.toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'});
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Frank', 'Bess', 'Ned']);
|
||||
});
|
||||
|
||||
it('should work up to 8 bindings', () => {
|
||||
let o3Comp: MyComp;
|
||||
let o4Comp: MyComp;
|
||||
let o5Comp: MyComp;
|
||||
let o6Comp: MyComp;
|
||||
let o7Comp: MyComp;
|
||||
let o8Comp: MyComp;
|
||||
|
||||
function Template(c: any, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, MyComp);
|
||||
o3Comp = m(1);
|
||||
e();
|
||||
E(2, MyComp);
|
||||
o4Comp = m(3);
|
||||
e();
|
||||
E(4, MyComp);
|
||||
o5Comp = m(5);
|
||||
e();
|
||||
E(6, MyComp);
|
||||
o6Comp = m(7);
|
||||
e();
|
||||
E(8, MyComp);
|
||||
o7Comp = m(9);
|
||||
e();
|
||||
E(10, MyComp);
|
||||
o8Comp = m(11);
|
||||
e();
|
||||
}
|
||||
p(0, 'names', o3(0, e0_literal, 5, c[5], 6, c[6], 7, c[7]));
|
||||
p(2, 'names', o4(1, e2_literal, 4, c[4], 5, c[5], 6, c[6], 7, c[7]));
|
||||
p(4, 'names', o5(2, e4_literal, 3, c[3], 4, c[4], 5, c[5], 6, c[6], 7, c[7]));
|
||||
p(6, 'names', o6(3, e6_literal, 2, c[2], 3, c[3], 4, c[4], 5, c[5], 6, c[6], 7, c[7]));
|
||||
p(8, 'names',
|
||||
o7(4, e8_literal, 1, c[1], 2, c[2], 3, c[3], 4, c[4], 5, c[5], 6, c[6], 7, c[7]));
|
||||
p(10, 'names',
|
||||
o8(5, e10_literal, 0, c[0], 1, c[1], 2, c[2], 3, c[3], 4, c[4], 5, c[5], 6, c[6], 7, c[7]));
|
||||
MyComp.ngComponentDef.h(1, 0);
|
||||
r(1, 0);
|
||||
MyComp.ngComponentDef.h(3, 2);
|
||||
r(3, 2);
|
||||
MyComp.ngComponentDef.h(5, 4);
|
||||
r(5, 4);
|
||||
MyComp.ngComponentDef.h(7, 6);
|
||||
r(7, 6);
|
||||
MyComp.ngComponentDef.h(9, 8);
|
||||
r(9, 8);
|
||||
MyComp.ngComponentDef.h(11, 10);
|
||||
r(11, 10);
|
||||
}
|
||||
|
||||
const e0_literal = ['a', 'b', 'c', 'd', 'e', null, null, null];
|
||||
const e2_literal = ['a', 'b', 'c', 'd', null, null, null, null];
|
||||
const e4_literal = ['a', 'b', 'c', null, null, null, null, null];
|
||||
const e6_literal = ['a', 'b', null, null, null, null, null, null];
|
||||
const e8_literal = ['a', null, null, null, null, null, null, null];
|
||||
const e10_literal = [null, null, null, null, null, null, null, null];
|
||||
|
||||
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']);
|
||||
expect(o3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(o4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(o5Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(o6Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(o7Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(o8Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
|
||||
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1', 'i1']);
|
||||
expect(o3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h1']);
|
||||
expect(o4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(o5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(o6Comp !.names).toEqual(['a', 'b', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(o7Comp !.names).toEqual(['a', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(o8Comp !.names).toEqual(['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
});
|
||||
|
||||
it('should support an object literal', () => {
|
||||
let objectComp: ObjectComp;
|
||||
|
||||
class ObjectComp {
|
||||
config: {[key: string]: any};
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ObjectComp,
|
||||
tag: 'object-comp',
|
||||
factory: function ObjectComp_Factory() { return objectComp = new ObjectComp(); },
|
||||
template: function ObjectComp_Template(ctx: ObjectComp, cm: boolean) {},
|
||||
inputs: {config: 'config'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <object-comp [config]="{duration: 500, animation: ctx.name}"></object-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, ObjectComp);
|
||||
e();
|
||||
}
|
||||
p(0, 'config', o1(0, e0_literal, 'animation', ctx.name));
|
||||
ObjectComp.ngComponentDef.h(1, 0);
|
||||
r(1, 0);
|
||||
}
|
||||
|
||||
const e0_literal = {duration: 500, animation: null};
|
||||
|
||||
renderToHtml(Template, {name: 'slide'});
|
||||
const firstObj = objectComp !.config;
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'slide'});
|
||||
|
||||
renderToHtml(Template, {name: 'slide'});
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'slide'});
|
||||
expect(firstObj).toBe(objectComp !.config);
|
||||
|
||||
renderToHtml(Template, {name: 'tap'});
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'tap'});
|
||||
|
||||
// Identity must change if binding changes
|
||||
expect(firstObj).not.toBe(objectComp !.config);
|
||||
|
||||
expect(e0_literal).toEqual({duration: 500, animation: null});
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue