diff --git a/modules/angular2/change_detection.js b/modules/angular2/change_detection.js index 26c7f4bee0..37449ba62f 100644 --- a/modules/angular2/change_detection.js +++ b/modules/angular2/change_detection.js @@ -35,19 +35,33 @@ export var defaultPipes = { ] }; -var _registry = new PipeRegistry(defaultPipes); - export class DynamicChangeDetection extends ChangeDetection { + registry:PipeRegistry; + + constructor(registry:PipeRegistry) { + super(); + this.registry = registry; + } + createProtoChangeDetector(name:string):ProtoChangeDetector{ - return new DynamicProtoChangeDetector(_registry); + return new DynamicProtoChangeDetector(this.registry); } } export class JitChangeDetection extends ChangeDetection { + registry:PipeRegistry; + + constructor(registry:PipeRegistry) { + super(); + this.registry = registry; + } + createProtoChangeDetector(name:string):ProtoChangeDetector{ - return new JitProtoChangeDetector(_registry); + return new JitProtoChangeDetector(this.registry); } } -export var dynamicChangeDetection = new DynamicChangeDetection(); -export var jitChangeDetection = new JitChangeDetection(); \ No newline at end of file +var _registry = new PipeRegistry(defaultPipes); + +export var dynamicChangeDetection = new DynamicChangeDetection(_registry); +export var jitChangeDetection = new JitChangeDetection(_registry); \ No newline at end of file diff --git a/modules/angular2/src/change_detection/change_detection_jit_generator.es6 b/modules/angular2/src/change_detection/change_detection_jit_generator.es6 index 80d025d9b8..b612d5efa2 100644 --- a/modules/angular2/src/change_detection/change_detection_jit_generator.es6 +++ b/modules/angular2/src/change_detection/change_detection_jit_generator.es6 @@ -14,7 +14,6 @@ import { RECORD_TYPE_INVOKE_CLOSURE, RECORD_TYPE_PRIMITIVE_OP, RECORD_TYPE_KEYED_ACCESS, - RECORD_TYPE_INVOKE_FORMATTER, RECORD_TYPE_PIPE, RECORD_TYPE_INTERPOLATE } from './proto_record'; @@ -26,10 +25,9 @@ import { * * For example: An expression `address.city` will result in the following class: * - * var ChangeDetector0 = function ChangeDetector0(dispatcher, formatters, protos) { + * var ChangeDetector0 = function ChangeDetector0(dispatcher, protos) { * AbstractChangeDetector.call(this); * this.dispatcher = dispatcher; - * this.formatters = formatters; * this.protos = protos; * * this.context = null; @@ -89,12 +87,11 @@ import { var ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector"; var UTIL = "ChangeDetectionUtil"; var DISPATCHER_ACCESSOR = "this.dispatcher"; -var FORMATTERS_ACCESSOR = "this.formatters"; +var PIPE_REGISTRY_ACCESSOR = "this.pipeRegistry"; var PROTOS_ACCESSOR = "this.protos"; var CHANGE_LOCAL = "change"; var CHANGES_LOCAL = "changes"; var TEMP_LOCAL = "temp"; -var PIPE_REGISTRY_ACCESSOR = "this.pipeRegistry"; function typeTemplate(type:string, cons:string, detectChanges:string, setContext:string):string { return ` @@ -102,18 +99,17 @@ ${cons} ${detectChanges} ${setContext}; -return function(dispatcher, formatters, pipeRegistry) { - return new ${type}(dispatcher, formatters, pipeRegistry, protos); +return function(dispatcher, pipeRegistry) { + return new ${type}(dispatcher, pipeRegistry, protos); } `; } function constructorTemplate(type:string, fieldsDefinitions:string):string { return ` -var ${type} = function ${type}(dispatcher, formatters, pipeRegistry, protos) { +var ${type} = function ${type}(dispatcher, pipeRegistry, protos) { ${ABSTRACT_CHANGE_DETECTOR}.call(this); ${DISPATCHER_ACCESSOR} = dispatcher; -${FORMATTERS_ACCESSOR} = formatters; ${PIPE_REGISTRY_ACCESSOR} = pipeRegistry; ${PROTOS_ACCESSOR} = protos; ${fieldsDefinitions} @@ -381,9 +377,6 @@ export class ChangeDetectorJITGenerator { case RECORD_TYPE_INTERPOLATE: return assignmentTemplate(newValue, this.genInterpolation(r)); - case RECORD_TYPE_INVOKE_FORMATTER: - return assignmentTemplate(newValue, `${FORMATTERS_ACCESSOR}.get("${r.name}")(${args})`); - case RECORD_TYPE_KEYED_ACCESS: var key = this.localNames[r.args[0]]; return assignmentTemplate(newValue, `${context}[${key}]`); diff --git a/modules/angular2/src/change_detection/dynamic_change_detector.js b/modules/angular2/src/change_detection/dynamic_change_detector.js index 3d6cdffd3a..054b50f7e3 100644 --- a/modules/angular2/src/change_detection/dynamic_change_detector.js +++ b/modules/angular2/src/change_detection/dynamic_change_detector.js @@ -16,7 +16,6 @@ import { RECORD_TYPE_INVOKE_CLOSURE, RECORD_TYPE_PRIMITIVE_OP, RECORD_TYPE_KEYED_ACCESS, - RECORD_TYPE_INVOKE_FORMATTER, RECORD_TYPE_PIPE, RECORD_TYPE_INTERPOLATE } from './proto_record'; @@ -25,7 +24,6 @@ import {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError} from './ex export class DynamicChangeDetector extends AbstractChangeDetector { dispatcher:any; - formatters:Map; pipeRegistry; values:List; @@ -35,10 +33,9 @@ export class DynamicChangeDetector extends AbstractChangeDetector { protos:List; - constructor(dispatcher:any, formatters:Map, pipeRegistry:PipeRegistry, protoRecords:List) { + constructor(dispatcher:any, pipeRegistry:PipeRegistry, protoRecords:List) { super(); this.dispatcher = dispatcher; - this.formatters = formatters; this.pipeRegistry = pipeRegistry; this.values = ListWrapper.createFixedSize(protoRecords.length + 1); @@ -149,10 +146,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector { case RECORD_TYPE_PRIMITIVE_OP: return FunctionWrapper.apply(proto.funcOrValue, this._readArgs(proto)); - case RECORD_TYPE_INVOKE_FORMATTER: - var formatter = MapWrapper.get(this.formatters, proto.funcOrValue); - return FunctionWrapper.apply(formatter, this._readArgs(proto)); - default: throw new BaseException(`Unknown operation ${proto.mode}`); } diff --git a/modules/angular2/src/change_detection/parser/ast.js b/modules/angular2/src/change_detection/parser/ast.js index 4ca3858c00..e2f1307a15 100644 --- a/modules/angular2/src/change_detection/parser/ast.js +++ b/modules/angular2/src/change_detection/parser/ast.js @@ -170,31 +170,15 @@ export class KeyedAccess extends AST { } } -export class Formatter extends AST { +export class Pipe extends AST { exp:AST; name:string; args:List; - allArgs:List; constructor(exp:AST, name:string, args:List) { super(); this.exp = exp; this.name = name; this.args = args; - this.allArgs = ListWrapper.concat([exp], args); - } - - visit(visitor) { - return visitor.visitFormatter(this); - } -} - -export class Pipe extends AST { - exp:AST; - name:string; - constructor(exp:AST, name:string) { - super(); - this.exp = exp; - this.name = name; } visit(visitor) { @@ -459,7 +443,6 @@ export class AstVisitor { visitBinary(ast:Binary) {} visitChain(ast:Chain){} visitConditional(ast:Conditional) {} - visitFormatter(ast:Formatter) {} visitPipe(ast:Pipe) {} visitFunctionCall(ast:FunctionCall) {} visitImplicitReceiver(ast:ImplicitReceiver) {} diff --git a/modules/angular2/src/change_detection/parser/parser.js b/modules/angular2/src/change_detection/parser/parser.js index 402e5f9e92..66d2f8423c 100644 --- a/modules/angular2/src/change_detection/parser/parser.js +++ b/modules/angular2/src/change_detection/parser/parser.js @@ -13,7 +13,6 @@ import { Binary, PrefixNot, Conditional, - Formatter, Pipe, Assignment, Chain, @@ -57,7 +56,7 @@ export class Parser { if (ListWrapper.isEmpty(pipes)) return bindingAst; var res = ListWrapper.reduce(pipes, - (result, currentPipeName) => new Pipe(result, currentPipeName), + (result, currentPipeName) => new Pipe(result, currentPipeName, []), bindingAst.ast); return new ASTWithSource(res, bindingAst.source, bindingAst.location); } @@ -191,7 +190,7 @@ class _ParseAST { parseChain():AST { var exprs = []; while (this.index < this.tokens.length) { - var expr = this.parseFormatter(); + var expr = this.parsePipe(); ListWrapper.push(exprs, expr); if (this.optionalCharacter($SEMICOLON)) { @@ -208,18 +207,18 @@ class _ParseAST { return new Chain(exprs); } - parseFormatter() { + parsePipe() { var result = this.parseExpression(); while (this.optionalOperator("|")) { if (this.parseAction) { - this.error("Cannot have a formatter in an action expression"); + this.error("Cannot have a pipe in an action expression"); } var name = this.expectIdentifierOrKeyword(); var args = ListWrapper.create(); while (this.optionalCharacter($COLON)) { ListWrapper.push(args, this.parseExpression()); } - result = new Formatter(result, name, args); + result = new Pipe(result, name, args); } return result; } @@ -380,7 +379,7 @@ class _ParseAST { parsePrimary() { if (this.optionalCharacter($LPAREN)) { - var result = this.parseFormatter(); + var result = this.parsePipe(); this.expectCharacter($RPAREN); return result; diff --git a/modules/angular2/src/change_detection/proto_change_detector.js b/modules/angular2/src/change_detection/proto_change_detector.js index 30d2ade411..dee42b9f22 100644 --- a/modules/angular2/src/change_detection/proto_change_detector.js +++ b/modules/angular2/src/change_detection/proto_change_detector.js @@ -10,7 +10,6 @@ import { Binary, Chain, Conditional, - Formatter, Pipe, FunctionCall, ImplicitReceiver, @@ -40,14 +39,13 @@ import { RECORD_TYPE_INVOKE_CLOSURE, RECORD_TYPE_PRIMITIVE_OP, RECORD_TYPE_KEYED_ACCESS, - RECORD_TYPE_INVOKE_FORMATTER, RECORD_TYPE_PIPE, RECORD_TYPE_INTERPOLATE } from './proto_record'; export class ProtoChangeDetector { addAst(ast:AST, bindingMemento:any, directiveMemento:any = null){} - instantiate(dispatcher:any, formatters:Map):ChangeDetector{ + instantiate(dispatcher:any):ChangeDetector{ return null; } } @@ -68,10 +66,9 @@ export class DynamicProtoChangeDetector extends ProtoChangeDetector { this._recordBuilder.addAst(ast, bindingMemento, directiveMemento); } - instantiate(dispatcher:any, formatters:Map) { + instantiate(dispatcher:any) { this._createRecordsIfNecessary(); - return new DynamicChangeDetector(dispatcher, formatters, - this._pipeRegistry, this._records); + return new DynamicChangeDetector(dispatcher, this._pipeRegistry, this._records); } _createRecordsIfNecessary() { @@ -99,9 +96,9 @@ export class JitProtoChangeDetector extends ProtoChangeDetector { this._recordBuilder.addAst(ast, bindingMemento, directiveMemento); } - instantiate(dispatcher:any, formatters:Map) { + instantiate(dispatcher:any) { this._createFactoryIfNecessary(); - return this._factory(dispatcher, formatters, this._pipeRegistry); + return this._factory(dispatcher, this._pipeRegistry); } _createFactoryIfNecessary() { @@ -178,10 +175,6 @@ class _ConvertAstIntoProtoRecords { return this._addRecord(RECORD_TYPE_PROPERTY, ast.name, ast.getter, [], null, receiver); } - visitFormatter(ast:Formatter) { - return this._addRecord(RECORD_TYPE_INVOKE_FORMATTER, ast.name, ast.name, this._visitAll(ast.allArgs), null, 0); - } - visitMethodCall(ast:MethodCall) { var receiver = ast.receiver.visit(this); var args = this._visitAll(ast.args); diff --git a/modules/angular2/src/change_detection/proto_record.js b/modules/angular2/src/change_detection/proto_record.js index 05d8edb7f4..d421d39d97 100644 --- a/modules/angular2/src/change_detection/proto_record.js +++ b/modules/angular2/src/change_detection/proto_record.js @@ -7,7 +7,6 @@ export const RECORD_TYPE_PROPERTY = 3; export const RECORD_TYPE_INVOKE_METHOD = 4; export const RECORD_TYPE_INVOKE_CLOSURE = 5; export const RECORD_TYPE_KEYED_ACCESS = 6; -export const RECORD_TYPE_INVOKE_FORMATTER = 7; export const RECORD_TYPE_PIPE = 8; export const RECORD_TYPE_INTERPOLATE = 9; @@ -54,7 +53,6 @@ export class ProtoRecord { isPureFunction():boolean { return this.mode === RECORD_TYPE_INTERPOLATE || - this.mode === RECORD_TYPE_INVOKE_FORMATTER || this.mode === RECORD_TYPE_PRIMITIVE_OP; } } diff --git a/modules/angular2/src/core/compiler/view.js b/modules/angular2/src/core/compiler/view.js index 5f6330e699..97e547df96 100644 --- a/modules/angular2/src/core/compiler/view.js +++ b/modules/angular2/src/core/compiler/view.js @@ -19,8 +19,6 @@ import {EventManager} from 'angular2/src/core/events/event_manager'; const NG_BINDING_CLASS = 'ng-binding'; const NG_BINDING_CLASS_SELECTOR = '.ng-binding'; -// TODO(tbosch): Cannot use `const` because of Dart. -var NO_FORMATTERS = MapWrapper.create(); // TODO(rado): make this configurable/smarter. var VIEW_POOL_CAPACITY = 10000; @@ -50,7 +48,7 @@ export class View { constructor(proto:ProtoView, nodes:List, protoChangeDetector:ProtoChangeDetector, protoContextLocals:Map) { this.proto = proto; this.nodes = nodes; - this.changeDetector = protoChangeDetector.instantiate(this, NO_FORMATTERS); + this.changeDetector = protoChangeDetector.instantiate(this); this.elementInjectors = null; this.rootElementInjectors = null; this.textNodes = null; diff --git a/modules/angular2/test/change_detection/change_detection_spec.js b/modules/angular2/test/change_detection/change_detection_spec.js index 9c020c9d1d..456056e8a5 100644 --- a/modules/angular2/test/change_detection/change_detection_spec.js +++ b/modules/angular2/test/change_detection/change_detection_spec.js @@ -3,7 +3,6 @@ import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, IS_DAR import {isPresent, isBlank, isJsObject, BaseException, FunctionWrapper} from 'angular2/src/facade/lang'; import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; -import {Pipe} from 'angular2/src/change_detection/parser/ast'; import {Parser} from 'angular2/src/change_detection/parser/parser'; import {Lexer} from 'angular2/src/change_detection/parser/lexer'; @@ -29,24 +28,18 @@ export function main() { return parser.parseBinding(exp, location); } - function createChangeDetector(memo:string, exp:string, context = null, formatters = null, - registry = null, pipeType:string = null) { + function createChangeDetector(memo:string, exp:string, context = null, registry = null) { var pcd = createProtoChangeDetector(registry); - var parsedAst = ast(exp); - if (isPresent(pipeType)) { - parsedAst = new Pipe(parsedAst, pipeType); - } - pcd.addAst(parsedAst, memo, memo); - + pcd.addAst(ast(exp), memo, memo); var dispatcher = new TestDispatcher(); - var cd = pcd.instantiate(dispatcher, formatters); + var cd = pcd.instantiate(dispatcher); cd.setContext(context); return {"changeDetector" : cd, "dispatcher" : dispatcher}; } - function executeWatch(memo:string, exp:string, context = null, formatters = null) { - var res = createChangeDetector(memo, exp, context, formatters); + function executeWatch(memo:string, exp:string, context = null) { + var res = createChangeDetector(memo, exp, context); res["changeDetector"].detectChanges(); return res["dispatcher"].log; } @@ -182,14 +175,6 @@ export function main() { }); }); - it("should support formatters", () => { - var formatters = MapWrapper.createFromPairs([ - ['uppercase', (v) => v.toUpperCase()], - ['wrap', (v, before, after) => `${before}${v}${after}`]]); - expect(executeWatch('str', '"aBc" | uppercase', null, formatters)).toEqual(['str=ABC']); - expect(executeWatch('str', '"b" | wrap:"a":"c"', null, formatters)).toEqual(['str=abc']); - }); - it("should support interpolation", () => { var parser = new Parser(new Lexer()); var pcd = createProtoChangeDetector(); @@ -197,7 +182,7 @@ export function main() { pcd.addAst(ast, "memo", "memo"); var dispatcher = new TestDispatcher(); - var cd = pcd.instantiate(dispatcher, MapWrapper.create()); + var cd = pcd.instantiate(dispatcher); cd.setContext(new TestData("value")); cd.detectChanges(); @@ -213,7 +198,7 @@ export function main() { pcd.addAst(ast("100 + 200"), "memo2", "2"); var dispatcher = new TestDispatcher(); - var cd = pcd.instantiate(dispatcher, null); + var cd = pcd.instantiate(dispatcher); cd.detectChanges(); @@ -227,7 +212,7 @@ export function main() { pcd.addAst(ast("c()"), "c", "2"); var dispatcher = new TestDispatcher(); - var cd = pcd.instantiate(dispatcher, null); + var cd = pcd.instantiate(dispatcher); var tr = new TestRecord(); tr.a = () => { @@ -256,7 +241,7 @@ export function main() { pcd.addAst(ast("a"), "a", 1); var dispatcher = new TestDispatcher(); - var cd = pcd.instantiate(dispatcher, null); + var cd = pcd.instantiate(dispatcher); cd.setContext(new TestData('value')); expect(() => { @@ -271,7 +256,7 @@ export function main() { var pcd = createProtoChangeDetector(); pcd.addAst(ast('invalidProp', 'someComponent'), "a", 1); - var cd = pcd.instantiate(new TestDispatcher(), null); + var cd = pcd.instantiate(new TestDispatcher()); cd.setContext(null); try { @@ -318,10 +303,10 @@ export function main() { beforeEach(() => { var protoParent = createProtoChangeDetector(); - parent = protoParent.instantiate(null, null); + parent = protoParent.instantiate(null); var protoChild = createProtoChangeDetector(); - child = protoChild.instantiate(null, null); + child = protoChild.instantiate(null); }); it("should add children", () => { @@ -340,25 +325,6 @@ export function main() { }); }); - describe("optimizations", () => { - it("should not rerun formatters when args did not change", () => { - var count = 0; - var formatters = MapWrapper.createFromPairs([ - ['count', (v) => {count ++; "value"}]]); - - var c = createChangeDetector('a', 'a | count', new TestData(null), formatters); - var cd = c["changeDetector"]; - - cd.detectChanges(); - - expect(count).toEqual(1); - - cd.detectChanges(); - - expect(count).toEqual(1); - }); - }); - describe("mode", () => { it("should not check a detached change detector", () => { var c = createChangeDetector('name', 'a', new TestData("value")); @@ -383,7 +349,7 @@ export function main() { }); it("should change CHECK_ONCE to CHECKED", () => { - var cd = createProtoChangeDetector().instantiate(null, null); + var cd = createProtoChangeDetector().instantiate(null); cd.mode = CHECK_ONCE; cd.detectChanges(); @@ -392,7 +358,7 @@ export function main() { }); it("should not change the CHECK_ALWAYS", () => { - var cd = createProtoChangeDetector().instantiate(null, null); + var cd = createProtoChangeDetector().instantiate(null); cd.mode = CHECK_ALWAYS; cd.detectChanges(); @@ -403,7 +369,7 @@ export function main() { describe("markPathToRootAsCheckOnce", () => { function changeDetector(mode, parent) { - var cd = createProtoChangeDetector().instantiate(null, null); + var cd = createProtoChangeDetector().instantiate(null); cd.mode = mode; if (isPresent(parent)) parent.addChild(cd); return cd; @@ -435,7 +401,7 @@ export function main() { var registry = new FakePipeRegistry('pipe', () => new CountingPipe()); var ctx = new Person("Megatron"); - var c = createChangeDetector("memo", "name", ctx, null, registry, 'pipe'); + var c = createChangeDetector("memo", "name | pipe", ctx, registry); var cd = c["changeDetector"]; var dispatcher = c["dispatcher"]; @@ -453,7 +419,7 @@ export function main() { var registry = new FakePipeRegistry('pipe', () => new OncePipe()); var ctx = new Person("Megatron"); - var c = createChangeDetector("memo", "name", ctx, null, registry, 'pipe'); + var c = createChangeDetector("memo", "name | pipe", ctx, registry); var cd = c["changeDetector"]; cd.detectChanges(); @@ -471,7 +437,7 @@ export function main() { var registry = new FakePipeRegistry('pipe', () => new IdentityPipe()) var ctx = new Person("Megatron"); - var c = createChangeDetector("memo", "name", ctx, null, registry, 'pipe'); + var c = createChangeDetector("memo", "name | pipe", ctx, registry); var cd = c["changeDetector"]; var dispatcher = c["dispatcher"]; diff --git a/modules/angular2/test/change_detection/parser/parser_spec.js b/modules/angular2/test/change_detection/parser/parser_spec.js index 925a0981d6..19e43ae7b9 100644 --- a/modules/angular2/test/change_detection/parser/parser_spec.js +++ b/modules/angular2/test/change_detection/parser/parser_spec.js @@ -5,7 +5,7 @@ import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; import {Parser} from 'angular2/src/change_detection/parser/parser'; import {Lexer} from 'angular2/src/change_detection/parser/lexer'; import {ContextWithVariableBindings} from 'angular2/src/change_detection/parser/context_with_variable_bindings'; -import {Formatter, LiteralPrimitive} from 'angular2/src/change_detection/parser/ast'; +import {Pipe, LiteralPrimitive} from 'angular2/src/change_detection/parser/ast'; class TestData { a; @@ -340,8 +340,8 @@ export function main() { }); }); - it("should error when using formatters", () => { - expectEvalError('x|blah').toThrowError(new RegExp('Cannot have a formatter')); + it("should error when using pipes", () => { + expectEvalError('x|blah').toThrowError(new RegExp('Cannot have a pipe')); }); it('should pass exceptions', () => { @@ -367,16 +367,16 @@ export function main() { }); describe("parseBinding", () => { - describe("formatters", () => { - it("should parse formatters", () => { + describe("pipes", () => { + it("should parse pipes", () => { var exp = parseBinding("'Foo'|uppercase").ast; - expect(exp).toBeAnInstanceOf(Formatter); + expect(exp).toBeAnInstanceOf(Pipe); expect(exp.name).toEqual("uppercase"); }); - it("should parse formatters with args", () => { + it("should parse pipes with args", () => { var exp = parseBinding("1|increment:2").ast; - expect(exp).toBeAnInstanceOf(Formatter); + expect(exp).toBeAnInstanceOf(Pipe); expect(exp.name).toEqual("increment"); expect(exp.args[0]).toBeAnInstanceOf(LiteralPrimitive); }); diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index 2914c366a5..03fb217b15 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -5,7 +5,8 @@ import {Map, MapWrapper} from 'angular2/src/facade/collection'; import {Type, isPresent} from 'angular2/src/facade/lang'; import {Injector} from 'angular2/di'; -import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection'; +import {Lexer, Parser, ChangeDetector, dynamicChangeDetection, + DynamicChangeDetection, Pipe, PipeRegistry} from 'angular2/change_detection'; import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler'; import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader'; @@ -24,9 +25,8 @@ export function main() { describe('integration tests', function() { var compiler, tplResolver; - beforeEach( () => { - tplResolver = new FakeTemplateResolver(); - compiler = new Compiler(dynamicChangeDetection, + function createCompiler(tplResolver, changedDetection) { + return new Compiler(changedDetection, new TemplateLoader(null), new DirectiveMetadataReader(), new Parser(new Lexer()), @@ -34,6 +34,11 @@ export function main() { new NativeShadowDomStrategy(), tplResolver ); + } + + beforeEach( () => { + tplResolver = new FakeTemplateResolver(); + compiler = createCompiler(tplResolver, dynamicChangeDetection); }); describe('react to record changes', function() { @@ -114,6 +119,33 @@ export function main() { }); }); + it("should support pipes in bindings and bind config", (done) => { + tplResolver.setTemplate(MyComp, + new Template({ + inline: '', + directives: [ComponentWithPipes] + })); + + + var registry = new PipeRegistry({ + "double" : [new DoublePipeFactory()] + }); + var changeDetection = new DynamicChangeDetection(registry); + var compiler = createCompiler(tplResolver, changeDetection); + compiler.compile(MyComp).then((pv) => { + createView(pv); + + ctx.ctxProp = 'a'; + cd.detectChanges(); + + var comp = view.contextWithLocals.get("comp"); + + // it is doubled twice: once in the binding, second time in the bind config + expect(comp.prop).toEqual('aaaa'); + done(); + }); + }); + it('should support nested components.', (done) => { tplResolver.setTemplate(MyComp, new Template({ inline: '', @@ -379,6 +411,20 @@ class MyComp { } } + +@Component({ + selector: 'component-with-pipes', + bind: { + "prop": "prop | double" + } +}) +@Template({ + inline: '' +}) +class ComponentWithPipes { + prop:string; +} + @Component({ selector: 'child-cmp', componentServices: [MyService] @@ -468,3 +514,24 @@ class FakeTemplateResolver extends TemplateResolver { return super.resolve(component); } } + + +class DoublePipe extends Pipe { + supports(obj) { + return true; + } + + transform(value) { + return `${value}${value}`; + } +} + +class DoublePipeFactory { + supports(obj) { + return true; + } + + create() { + return new DoublePipe(); + } +} \ No newline at end of file diff --git a/modules/benchmarks/src/change_detection/change_detection_benchmark.js b/modules/benchmarks/src/change_detection/change_detection_benchmark.js index 03abf9d80e..7df4cd7cf5 100644 --- a/modules/benchmarks/src/change_detection/change_detection_benchmark.js +++ b/modules/benchmarks/src/change_detection/change_detection_benchmark.js @@ -103,7 +103,7 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations) { var parser = new Parser(new Lexer()); var parentProto = changeDetection.createProtoChangeDetector('parent'); - var parentCd = parentProto.instantiate(dispatcher, MapWrapper.create()); + var parentCd = parentProto.instantiate(dispatcher); var proto = changeDetection.createProtoChangeDetector("proto"); var astWithSource = [ @@ -127,7 +127,7 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations) { for (var j = 0; j < 10; ++j) { obj.setField(j, i); } - var cd = proto.instantiate(dispatcher, null); + var cd = proto.instantiate(dispatcher); cd.setContext(obj); parentCd.addChild(cd); }