diff --git a/modules/angular2/src/compiler/change_detector_compiler.ts b/modules/angular2/src/compiler/change_detector_compiler.ts new file mode 100644 index 0000000000..412e06a449 --- /dev/null +++ b/modules/angular2/src/compiler/change_detector_compiler.ts @@ -0,0 +1,81 @@ +import {TypeMetadata, SourceModule} from './api'; +import { + ChangeDetectorJITGenerator +} from 'angular2/src/core/change_detection/change_detection_jit_generator'; + +import {createChangeDetectorDefinitions} from './change_definition_factory'; +import {isJsObject, CONST_EXPR} from 'angular2/src/core/facade/lang'; + +import { + ChangeDetectorGenConfig, + ChangeDetectorDefinition, + DynamicProtoChangeDetector, + ChangeDetectionStrategy +} from 'angular2/src/core/change_detection/change_detection'; + +import {TemplateAst} from './template_ast'; +import {Codegen} from 'angular2/src/transform/template_compiler/change_detector_codegen'; + +var IS_DART = !isJsObject({}); + +const ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector"; +const UTIL = "ChangeDetectionUtil"; + +const JS_CHANGE_DETECTOR_IMPORTS = CONST_EXPR([ + ['angular2/src/core/change_detection/abstract_change_detector', 'acd'], + ['angular2/src/core/change_detection/change_detection_util', 'cdu'] +]); + +const DART_CHANGE_DETECTOR_IMPORTS = + CONST_EXPR([['angular2/src/core/change_detection/pregen_proto_change_detector', '_gen']]); + +export class ChangeDetectionCompiler { + constructor(private _genConfig: ChangeDetectorGenConfig) {} + + compileComponentRuntime(componentType: TypeMetadata, strategy: ChangeDetectionStrategy, + parsedTemplate: TemplateAst[]): Function[] { + var changeDetectorDefinitions = + createChangeDetectorDefinitions(componentType, strategy, this._genConfig, parsedTemplate); + return changeDetectorDefinitions.map(definition => + this._createChangeDetectorFactory(definition)); + } + + private _createChangeDetectorFactory(definition: ChangeDetectorDefinition): Function { + if (IS_DART) { + var proto = new DynamicProtoChangeDetector(definition); + return (dispatcher) => proto.instantiate(dispatcher); + } else { + // TODO(tbosch): provide a flag in _genConfig whether to allow eval or fall back to dynamic + // change detection as well! + return new ChangeDetectorJITGenerator(definition, UTIL, ABSTRACT_CHANGE_DETECTOR).generate(); + } + } + + compileComponentCodeGen(componentType: TypeMetadata, strategy: ChangeDetectionStrategy, + parsedTemplate: TemplateAst[]): SourceModule { + var changeDetectorDefinitions = + createChangeDetectorDefinitions(componentType, strategy, this._genConfig, parsedTemplate); + var imports = IS_DART ? DART_CHANGE_DETECTOR_IMPORTS : JS_CHANGE_DETECTOR_IMPORTS; + var factories = []; + var sourceParts = changeDetectorDefinitions.map(definition => { + var codegen: any; + // TODO(tbosch): move the 2 code generators to the same place, one with .dart and one with .ts + // suffix + // and have the same API for calling them! + if (IS_DART) { + codegen = new Codegen(); + var className = definition.id; + codegen.generate(componentType.typeName, className, definition); + factories.push(`(dispatcher) => new ${className}(dispatcher)`); + return codegen.toString(); + } else { + codegen = new ChangeDetectorJITGenerator(definition, `cdu.${UTIL}`, + `acd.${ABSTRACT_CHANGE_DETECTOR}`); + factories.push(`function(dispatcher) { return new ${codegen.typeName}(dispatcher); }`); + return codegen.generateSource(); + } + }); + sourceParts.push(`var CHANGE_DETECTORS = [ ${factories.join(',')} ];`); + return new SourceModule(componentType.typeUrl, sourceParts.join('\n'), imports); + } +} diff --git a/modules/angular2/src/compiler/style_compiler.ts b/modules/angular2/src/compiler/style_compiler.ts index 50c035ab35..085993c69b 100644 --- a/modules/angular2/src/compiler/style_compiler.ts +++ b/modules/angular2/src/compiler/style_compiler.ts @@ -76,7 +76,7 @@ export class StyleCompiler { private _styleCodeGen(moduleName: string, plainStyles: string[], absUrls: string[], shim: boolean, suffix: string): SourceModule { var imports: string[][] = []; - var moduleSource = `${codeGenExportVar('STYLES')} (`; + var moduleSource = `var STYLES = (`; moduleSource += `[${plainStyles.map( plainStyle => escapeString(this._shimIfNeeded(plainStyle, shim)) ).join(',')}]`; for (var i = 0; i < absUrls.length; i++) { @@ -109,14 +109,6 @@ function escapeString(input: string): string { return `'${escapedInput}'`; } -function codeGenExportVar(name: string): string { - if (IS_DART) { - return `var ${name} =`; - } else { - return `var ${name} = exports.${name} =`; - } -} - function codeGenConcatArray(expression: string): string { return `${IS_DART ? '..addAll' : '.concat'}(${expression})`; } diff --git a/modules/angular2/src/core/change_detection/change_detection.ts b/modules/angular2/src/core/change_detection/change_detection.ts index 4bd3aeb13e..19c69e8bd4 100644 --- a/modules/angular2/src/core/change_detection/change_detection.ts +++ b/modules/angular2/src/core/change_detection/change_detection.ts @@ -103,7 +103,7 @@ export class PreGeneratedChangeDetection extends ChangeDetection { this._genConfig = isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(), - assertionsEnabled(), false); + assertionsEnabled(), false, false); } static isSupported(): boolean { return PregenProtoChangeDetector.isSupported(); } @@ -133,7 +133,7 @@ export class DynamicChangeDetection extends ChangeDetection { super(); this._genConfig = isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(), - assertionsEnabled(), false); + assertionsEnabled(), false, false); } getProtoChangeDetector(id: string, definition: ChangeDetectorDefinition): ProtoChangeDetector { @@ -157,7 +157,7 @@ export class JitChangeDetection extends ChangeDetection { super(); this._genConfig = isPresent(config) ? config : new ChangeDetectorGenConfig(assertionsEnabled(), - assertionsEnabled(), false); + assertionsEnabled(), false, true); } static isSupported(): boolean { return JitProtoChangeDetector.isSupported(); } diff --git a/modules/angular2/src/core/change_detection/change_detection_jit_generator.dart b/modules/angular2/src/core/change_detection/change_detection_jit_generator.dart index 04069bf189..6010a73011 100644 --- a/modules/angular2/src/core/change_detection/change_detection_jit_generator.dart +++ b/modules/angular2/src/core/change_detection/change_detection_jit_generator.dart @@ -7,11 +7,16 @@ library change_detection.change_detection_jit_generator; /// `PregenProtoChangeDetector`, and /// `src/transform/template_compiler/change_detector_codegen.dart` for details. class ChangeDetectorJITGenerator { - ChangeDetectorJITGenerator(typeName, strategy, records, directiveMementos) {} + String typeName; + ChangeDetectorJITGenerator(definition, changeDetectionUtilVarName, abstractChangeDetectorVarName) {} generate() { throw "Jit Change Detection is not supported in Dart"; } + generateSource() { + throw "Jit Change Detection is not supported in Dart"; + } + static bool isSupported() => false; } diff --git a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts index 5243570fb4..adfbf435ed 100644 --- a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts +++ b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts @@ -1,4 +1,10 @@ -import {BaseException, Type, isBlank, isPresent} from 'angular2/src/core/facade/lang'; +import { + BaseException, + Type, + isBlank, + isPresent, + StringWrapper +} from 'angular2/src/core/facade/lang'; import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; import {AbstractChangeDetector} from './abstract_change_detector'; @@ -11,10 +17,9 @@ import {CodegenLogicUtil} from './codegen_logic_util'; import {codify} from './codegen_facade'; import {EventBinding} from './event_binding'; import {BindingTarget} from './binding_record'; -import {ChangeDetectorGenConfig} from './interfaces'; +import {ChangeDetectorGenConfig, ChangeDetectorDefinition} from './interfaces'; import {ChangeDetectionStrategy} from './constants'; - - +import {createPropertyRecords, createEventRecords} from './proto_change_detector'; /** * The code generator takes a list of proto records and creates a function/class @@ -25,39 +30,65 @@ import {ChangeDetectionStrategy} from './constants'; * `angular2.transform.template_compiler.change_detector_codegen` library. If you make updates * here, please make equivalent changes there. */ -const ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector"; -const UTIL = "ChangeDetectionUtil"; const IS_CHANGED_LOCAL = "isChanged"; const CHANGES_LOCAL = "changes"; export class ChangeDetectorJITGenerator { - _logic: CodegenLogicUtil; - _names: CodegenNameUtil; - _typeName: string; + private _logic: CodegenLogicUtil; + private _names: CodegenNameUtil; + private id: string; + private changeDetectionStrategy: ChangeDetectionStrategy; + private records: ProtoRecord[]; + private propertyBindingTargets: BindingTarget[]; + private eventBindings: EventBinding[]; + private directiveRecords: any[]; + private genConfig: ChangeDetectorGenConfig; + typeName: string; - constructor(private id: string, private changeDetectionStrategy: ChangeDetectionStrategy, - private records: ProtoRecord[], private propertyBindingTargets: BindingTarget[], - private eventBindings: EventBinding[], private directiveRecords: any[], - private genConfig: ChangeDetectorGenConfig) { - this._names = - new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords, UTIL); - this._logic = new CodegenLogicUtil(this._names, UTIL, changeDetectionStrategy); - this._typeName = sanitizeName(`ChangeDetector_${this.id}`); + constructor(definition: ChangeDetectorDefinition, private changeDetectionUtilVarName: string, + private abstractChangeDetectorVarName: string) { + var propertyBindingRecords = createPropertyRecords(definition); + var eventBindingRecords = createEventRecords(definition); + var propertyBindingTargets = definition.bindingRecords.map(b => b.target); + this.id = definition.id; + this.changeDetectionStrategy = definition.strategy; + this.genConfig = definition.genConfig; + + this.records = propertyBindingRecords; + this.propertyBindingTargets = propertyBindingTargets; + this.eventBindings = eventBindingRecords; + this.directiveRecords = definition.directiveRecords; + this._names = new CodegenNameUtil(this.records, this.eventBindings, this.directiveRecords, + this.changeDetectionUtilVarName); + this._logic = new CodegenLogicUtil(this._names, this.changeDetectionUtilVarName, + this.changeDetectionStrategy); + this.typeName = sanitizeName(`ChangeDetector_${this.id}`); } generate(): Function { - var classDefinition = ` - var ${this._typeName} = function ${this._typeName}(dispatcher) { - ${ABSTRACT_CHANGE_DETECTOR}.call( + var factorySource = ` + ${this.generateSource()} + return function(dispatcher) { + return new ${this.typeName}(dispatcher); + } + `; + return new Function(this.abstractChangeDetectorVarName, this.changeDetectionUtilVarName, + factorySource)(AbstractChangeDetector, ChangeDetectionUtil); + } + + generateSource(): string { + return ` + var ${this.typeName} = function ${this.typeName}(dispatcher) { + ${this.abstractChangeDetectorVarName}.call( this, ${JSON.stringify(this.id)}, dispatcher, ${this.records.length}, - ${this._typeName}.gen_propertyBindingTargets, ${this._typeName}.gen_directiveIndices, + ${this.typeName}.gen_propertyBindingTargets, ${this.typeName}.gen_directiveIndices, ${codify(this.changeDetectionStrategy)}); this.dehydrateDirectives(false); } - ${this._typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype); + ${this.typeName}.prototype = Object.create(${this.abstractChangeDetectorVarName}.prototype); - ${this._typeName}.prototype.detectChangesInRecordsInternal = function(throwOnChange) { + ${this.typeName}.prototype.detectChangesInRecordsInternal = function(throwOnChange) { ${this._names.genInitLocals()} var ${IS_CHANGED_LOCAL} = false; var ${CHANGES_LOCAL} = null; @@ -80,31 +111,25 @@ export class ChangeDetectorJITGenerator { ${this._genPropertyBindingTargets()} ${this._genDirectiveIndices()} - - return function(dispatcher) { - return new ${this._typeName}(dispatcher); - } `; - return new Function(ABSTRACT_CHANGE_DETECTOR, UTIL, classDefinition)(AbstractChangeDetector, - ChangeDetectionUtil); } _genPropertyBindingTargets(): string { var targets = this._logic.genPropertyBindingTargets(this.propertyBindingTargets, this.genConfig.genDebugInfo); - return `${this._typeName}.gen_propertyBindingTargets = ${targets};`; + return `${this.typeName}.gen_propertyBindingTargets = ${targets};`; } _genDirectiveIndices(): string { var indices = this._logic.genDirectiveIndices(this.directiveRecords); - return `${this._typeName}.gen_directiveIndices = ${indices};`; + return `${this.typeName}.gen_directiveIndices = ${indices};`; } _maybeGenHandleEventInternal(): string { if (this.eventBindings.length > 0) { var handlers = this.eventBindings.map(eb => this._genEventBinding(eb)).join("\n"); return ` - ${this._typeName}.prototype.handleEventInternal = function(eventName, elIndex, locals) { + ${this.typeName}.prototype.handleEventInternal = function(eventName, elIndex, locals) { var ${this._names.getPreventDefaultAccesor()} = false; ${this._names.genInitEventLocals()} ${handlers} @@ -156,7 +181,7 @@ export class ChangeDetectorJITGenerator { } var dehydrateFieldsCode = this._names.genDehydrateFields(); if (!destroyPipesCode && !dehydrateFieldsCode) return ''; - return `${this._typeName}.prototype.dehydrateDirectives = function(destroyPipes) { + return `${this.typeName}.prototype.dehydrateDirectives = function(destroyPipes) { ${destroyPipesCode} ${dehydrateFieldsCode} }`; @@ -166,7 +191,7 @@ export class ChangeDetectorJITGenerator { var hydrateDirectivesCode = this._logic.genHydrateDirectives(this.directiveRecords); var hydrateDetectorsCode = this._logic.genHydrateDetectors(this.directiveRecords); if (!hydrateDirectivesCode && !hydrateDetectorsCode) return ''; - return `${this._typeName}.prototype.hydrateDirectives = function(directives) { + return `${this.typeName}.prototype.hydrateDirectives = function(directives) { ${hydrateDirectivesCode} ${hydrateDetectorsCode} }`; @@ -177,7 +202,7 @@ export class ChangeDetectorJITGenerator { if (notifications.length > 0) { var directiveNotifications = notifications.join("\n"); return ` - ${this._typeName}.prototype.afterContentLifecycleCallbacksInternal = function() { + ${this.typeName}.prototype.afterContentLifecycleCallbacksInternal = function() { ${directiveNotifications} } `; @@ -191,7 +216,7 @@ export class ChangeDetectorJITGenerator { if (notifications.length > 0) { var directiveNotifications = notifications.join("\n"); return ` - ${this._typeName}.prototype.afterViewLifecycleCallbacksInternal = function() { + ${this.typeName}.prototype.afterViewLifecycleCallbacksInternal = function() { ${directiveNotifications} } `; @@ -239,7 +264,7 @@ export class ChangeDetectorJITGenerator { var pipeName = r.name; var init = ` - if (${pipe} === ${UTIL}.uninitialized) { + if (${pipe} === ${this.changeDetectionUtilVarName}.uninitialized) { ${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeName}'); } `; @@ -251,7 +276,7 @@ export class ChangeDetectorJITGenerator { var check = ` if (${oldValue} !== ${newValue}) { - ${newValue} = ${UTIL}.unwrapValue(${newValue}) + ${newValue} = ${this.changeDetectionUtilVarName}.unwrapValue(${newValue}) ${this._genChangeMarker(r)} ${this._genUpdateDirectiveOrElement(r)} ${this._genAddToChanges(r)} @@ -342,7 +367,7 @@ export class ChangeDetectorJITGenerator { _genCheckNoChanges(): string { if (this.genConfig.genCheckNoChanges) { - return `${this._typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`; + return `${this.typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`; } else { return ''; } diff --git a/modules/angular2/src/core/change_detection/interfaces.ts b/modules/angular2/src/core/change_detection/interfaces.ts index 7efe7e8f63..c2e5f5c0e8 100644 --- a/modules/angular2/src/core/change_detection/interfaces.ts +++ b/modules/angular2/src/core/change_detection/interfaces.ts @@ -77,7 +77,7 @@ export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher) export class ChangeDetectorGenConfig { constructor(public genCheckNoChanges: boolean, public genDebugInfo: boolean, - public logBindingUpdate: boolean) {} + public logBindingUpdate: boolean, public useJit: boolean) {} } export class ChangeDetectorDefinition { diff --git a/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts b/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts index b143287fe6..ca99ddccfb 100644 --- a/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts +++ b/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts @@ -4,9 +4,6 @@ import {isPresent} from 'angular2/src/core/facade/lang'; import {ProtoChangeDetector, ChangeDetector, ChangeDetectorDefinition} from './interfaces'; import {ChangeDetectorJITGenerator} from './change_detection_jit_generator'; -import {coalesce} from './coalesce'; -import {createPropertyRecords, createEventRecords} from './proto_change_detector'; - export class JitProtoChangeDetector implements ProtoChangeDetector { _factory: Function; @@ -19,13 +16,6 @@ export class JitProtoChangeDetector implements ProtoChangeDetector { instantiate(dispatcher: any): ChangeDetector { return this._factory(dispatcher); } _createFactory(definition: ChangeDetectorDefinition) { - var propertyBindingRecords = createPropertyRecords(definition); - var eventBindingRecords = createEventRecords(definition); - var propertyBindingTargets = this.definition.bindingRecords.map(b => b.target); - - return new ChangeDetectorJITGenerator( - definition.id, definition.strategy, propertyBindingRecords, propertyBindingTargets, - eventBindingRecords, this.definition.directiveRecords, this.definition.genConfig) - .generate(); + return new ChangeDetectorJITGenerator(definition, 'util', 'AbstractChangeDetector').generate(); } } diff --git a/modules/angular2/src/transform/template_compiler/change_detector_codegen.ts b/modules/angular2/src/transform/template_compiler/change_detector_codegen.ts new file mode 100644 index 0000000000..03d340e5d6 --- /dev/null +++ b/modules/angular2/src/transform/template_compiler/change_detector_codegen.ts @@ -0,0 +1,14 @@ +import { + ChangeDetectorDefinition, +} from 'angular2/src/core/change_detection/change_detection'; + +// Note: This class is only here so that we can reference it from TypeScript code. +// The actual implementation lives under modules_dart. +// TODO(tbosch): Move the corresponding code into angular2/src/compiler once +// the new compiler is done. +export class Codegen { + generate(typeName: string, changeDetectorTypeName: string, def: ChangeDetectorDefinition): void { + throw "Not implemented in JS"; + } + toString(): string { throw "Not implemented in JS"; } +} \ No newline at end of file diff --git a/modules/angular2/test/compiler/change_definition_factory_spec.ts b/modules/angular2/test/compiler/change_definition_factory_spec.ts index 0fcc802b7f..4c15b665fa 100644 --- a/modules/angular2/test/compiler/change_definition_factory_spec.ts +++ b/modules/angular2/test/compiler/change_definition_factory_spec.ts @@ -12,7 +12,6 @@ import { TestComponentBuilder } from 'angular2/test_lib'; import {MapWrapper} from 'angular2/src/core/facade/collection'; -import {isBlank} from 'angular2/src/core/facade/lang'; import {HtmlParser} from 'angular2/src/compiler/html_parser'; import {DirectiveMetadata, TypeMetadata, ChangeDetectionMetadata} from 'angular2/src/compiler/api'; import {MockSchemaRegistry} from './template_parser_spec'; @@ -23,7 +22,6 @@ import { ChangeDetectorDefinition, ChangeDetectorGenConfig, DynamicProtoChangeDetector, - ProtoChangeDetector, ChangeDetectionStrategy, ChangeDispatcher, DirectiveIndex, @@ -33,6 +31,7 @@ import { } from 'angular2/src/core/change_detection/change_detection'; import {Pipes} from 'angular2/src/core/change_detection/pipes'; import {createChangeDetectorDefinitions} from 'angular2/src/compiler/change_definition_factory'; +import {TestContext, TestDirective, TestDispatcher, TestPipes} from './change_detector_mocks'; export function main() { describe('ChangeDefinitionFactory', () => { @@ -62,8 +61,8 @@ export function main() { protoViewIndex: number = 0): ChangeDetector { var protoChangeDetectors = createChangeDetectorDefinitions( - new TypeMetadata({typeName: 'SomeComp'}), ChangeDetectionStrategy.CheckAlways, - new ChangeDetectorGenConfig(true, true, false), + new TypeMetadata({typeName: 'SomeComp'}), ChangeDetectionStrategy.Default, + new ChangeDetectorGenConfig(true, true, false, false), parser.parse(domParser.parse(template, 'TestComp'), directives)) .map(definition => new DynamicProtoChangeDetector(definition)); var changeDetector = protoChangeDetectors[protoViewIndex].instantiate(dispatcher); @@ -164,47 +163,3 @@ export function main() { }); }); } - -class TestContext { - eventLog: string[] = []; - someProp: string; - someProp2: string; - - onEvent(value: string) { this.eventLog.push(value); } -} - -class TestDirective { - eventLog: string[] = []; - dirProp: string; - - onEvent(value: string) { this.eventLog.push(value); } -} - -class TestDispatcher implements ChangeDispatcher { - log: string[]; - - constructor(public directives: any[], public detectors: ProtoChangeDetector[]) { this.clear(); } - - getDirectiveFor(di: DirectiveIndex) { return this.directives[di.directiveIndex]; } - - getDetectorFor(di: DirectiveIndex) { return this.detectors[di.directiveIndex]; } - - clear() { this.log = []; } - - notifyOnBinding(target: BindingTarget, value) { - this.log.push(`${target.mode}(${target.name})=${this._asString(value)}`); - } - - logBindingUpdate(target, value) {} - - notifyAfterContentChecked() {} - notifyAfterViewChecked() {} - - getDebugContext(a, b) { return null; } - - _asString(value) { return (isBlank(value) ? 'null' : value.toString()); } -} - -class TestPipes implements Pipes { - get(type: string) { return null; } -} diff --git a/modules/angular2/test/compiler/change_detector_compiler_spec.ts b/modules/angular2/test/compiler/change_detector_compiler_spec.ts new file mode 100644 index 0000000000..1b7e55234d --- /dev/null +++ b/modules/angular2/test/compiler/change_detector_compiler_spec.ts @@ -0,0 +1,138 @@ +import { + ddescribe, + describe, + xdescribe, + it, + iit, + xit, + expect, + beforeEach, + afterEach, + AsyncTestCompleter, + inject +} from 'angular2/test_lib'; +import {IS_DART} from '../platform'; + +import {CONST_EXPR} from 'angular2/src/core/facade/lang'; +import {MapWrapper} from 'angular2/src/core/facade/collection'; +import {Promise} from 'angular2/src/core/facade/async'; + +import {ChangeDetectionCompiler} from 'angular2/src/compiler/change_detector_compiler'; + +import {HtmlParser} from 'angular2/src/compiler/html_parser'; +import { + DirectiveMetadata, + TypeMetadata, + ChangeDetectionMetadata, + SourceModule +} from 'angular2/src/compiler/api'; + +import {MockSchemaRegistry} from './template_parser_spec'; + +import {TemplateParser} from 'angular2/src/compiler/template_parser'; + +import { + Parser, + Lexer, + ChangeDetectorGenConfig, + ChangeDetectionStrategy, + ChangeDispatcher, + DirectiveIndex, + Locals, + BindingTarget, + ChangeDetector +} from 'angular2/src/core/change_detection/change_detection'; + +import {evalModule} from './eval_module'; + +import {TestContext, TestDispatcher, TestPipes} from './change_detector_mocks'; + +// Attention: These module names have to correspond to real modules! +const MODULE_NAME = 'angular2/test/compiler/change_detector_compiler_spec'; + +export function main() { + describe('ChangeDetectorCompiler', () => { + var domParser: HtmlParser; + var parser: TemplateParser; + + function createCompiler(useJit: boolean): ChangeDetectionCompiler { + return new ChangeDetectionCompiler(new ChangeDetectorGenConfig(true, true, false, useJit)); + } + + beforeEach(() => { + domParser = new HtmlParser(); + parser = new TemplateParser( + new Parser(new Lexer()), + new MockSchemaRegistry({'invalidProp': false}, {'mappedAttr': 'mappedProp'})); + }); + + describe('compileComponentRuntime', () => { + function detectChanges(compiler: ChangeDetectionCompiler, template: string, + directives: DirectiveMetadata[] = CONST_EXPR([])): string[] { + var type = new TypeMetadata({typeName: 'SomeComp'}); + var parsedTemplate = parser.parse(domParser.parse(template, 'TestComp'), directives); + var factories = + compiler.compileComponentRuntime(type, ChangeDetectionStrategy.Default, parsedTemplate); + return testChangeDetector(factories[0]); + } + + it('should watch element properties (no jit)', () => { + expect(detectChanges(createCompiler(false), '