parent
							
								
									9889c21aaa
								
							
						
					
					
						commit
						2f7045720a
					
				| @ -9,6 +9,7 @@ import { | ||||
| import * as o from './output_ast'; | ||||
| import {EmitterVisitorContext} from './abstract_emitter'; | ||||
| import {AbstractJsEmitterVisitor} from './abstract_js_emitter'; | ||||
| import {sanitizeIdentifier} from '../util'; | ||||
| 
 | ||||
| export function jitStatements(sourceUrl: string, statements: o.Statement[], | ||||
|                               resultVar: string): any { | ||||
| @ -36,13 +37,10 @@ class JitEmitterVisitor extends AbstractJsEmitterVisitor { | ||||
|     if (id === -1) { | ||||
|       id = this._evalArgValues.length; | ||||
|       this._evalArgValues.push(value); | ||||
|       this._evalArgNames.push(sanitizeJitArgName(`jit_${ast.value.name}${id}`)); | ||||
|       var name = isPresent(ast.value.name) ? sanitizeIdentifier(ast.value.name) : 'val'; | ||||
|       this._evalArgNames.push(sanitizeIdentifier(`jit_${name}${id}`)); | ||||
|     } | ||||
|     ctx.print(this._evalArgNames[id]); | ||||
|     return null; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function sanitizeJitArgName(name: string): string { | ||||
|   return StringWrapper.replaceAll(name, /[\.\/]/g, '_'); | ||||
| } | ||||
|  | ||||
| @ -24,7 +24,7 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/metadata | ||||
| import {reflector} from 'angular2/src/core/reflection/reflection'; | ||||
| import {Injectable, Inject, Optional} from 'angular2/src/core/di'; | ||||
| import {PLATFORM_DIRECTIVES, PLATFORM_PIPES} from 'angular2/src/core/platform_directives_and_pipes'; | ||||
| import {MODULE_SUFFIX} from './util'; | ||||
| import {MODULE_SUFFIX, sanitizeIdentifier} from './util'; | ||||
| import {assertArrayOfStrings} from './assertions'; | ||||
| import {getUrlScheme} from 'angular2/src/compiler/url_resolver'; | ||||
| import {Provider} from 'angular2/src/core/di/provider'; | ||||
| @ -52,20 +52,18 @@ export class RuntimeMetadataResolver { | ||||
|               @Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[], | ||||
|               @Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Type[]) {} | ||||
| 
 | ||||
|   /** | ||||
|    * Wrap the stringify method to avoid naming things `function (arg1...) {` | ||||
|    */ | ||||
|   private sanitizeName(obj: any): string { | ||||
|     let result = StringWrapper.replaceAll(stringify(obj), /[\s-]/g, '_'); | ||||
|     if (result.indexOf('(') < 0) { | ||||
|       return result; | ||||
|   private sanitizeTokenName(token: any): string { | ||||
|     let identifier = stringify(token); | ||||
|     if (identifier.indexOf('(') >= 0) { | ||||
|       // case: anonymous functions!
 | ||||
|       let found = this._anonymousTypes.get(token); | ||||
|       if (isBlank(found)) { | ||||
|         this._anonymousTypes.set(token, this._anonymousTypeIndex++); | ||||
|         found = this._anonymousTypes.get(token); | ||||
|       } | ||||
|       identifier = `anonymous_token_${found}_`; | ||||
|     } | ||||
|     let found = this._anonymousTypes.get(obj); | ||||
|     if (isBlank(found)) { | ||||
|       this._anonymousTypes.set(obj, this._anonymousTypeIndex++); | ||||
|       found = this._anonymousTypes.get(obj); | ||||
|     } | ||||
|     return `anonymous_type_${found}_`; | ||||
|     return sanitizeIdentifier(identifier); | ||||
|   } | ||||
| 
 | ||||
|   getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata { | ||||
| @ -130,7 +128,7 @@ export class RuntimeMetadataResolver { | ||||
| 
 | ||||
|   getTypeMetadata(type: Type, moduleUrl: string): cpl.CompileTypeMetadata { | ||||
|     return new cpl.CompileTypeMetadata({ | ||||
|       name: this.sanitizeName(type), | ||||
|       name: this.sanitizeTokenName(type), | ||||
|       moduleUrl: moduleUrl, | ||||
|       runtime: type, | ||||
|       diDeps: this.getDependenciesMetadata(type, null) | ||||
| @ -139,7 +137,7 @@ export class RuntimeMetadataResolver { | ||||
| 
 | ||||
|   getFactoryMetadata(factory: Function, moduleUrl: string): cpl.CompileFactoryMetadata { | ||||
|     return new cpl.CompileFactoryMetadata({ | ||||
|       name: this.sanitizeName(factory), | ||||
|       name: this.sanitizeTokenName(factory), | ||||
|       moduleUrl: moduleUrl, | ||||
|       runtime: factory, | ||||
|       diDeps: this.getDependenciesMetadata(factory, null) | ||||
| @ -227,17 +225,16 @@ export class RuntimeMetadataResolver { | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   getRuntimeIdentifier(value: any): cpl.CompileIdentifierMetadata { | ||||
|     return new cpl.CompileIdentifierMetadata({runtime: value, name: this.sanitizeName(value)}); | ||||
|   } | ||||
| 
 | ||||
|   getTokenMetadata(token: any): cpl.CompileTokenMetadata { | ||||
|     token = resolveForwardRef(token); | ||||
|     var compileToken; | ||||
|     if (isString(token)) { | ||||
|       compileToken = new cpl.CompileTokenMetadata({value: token}); | ||||
|     } else { | ||||
|       compileToken = new cpl.CompileTokenMetadata({identifier: this.getRuntimeIdentifier(token)}); | ||||
|       compileToken = new cpl.CompileTokenMetadata({ | ||||
|         identifier: new cpl.CompileIdentifierMetadata( | ||||
|             {runtime: token, name: this.sanitizeTokenName(token)}) | ||||
|       }); | ||||
|     } | ||||
|     return compileToken; | ||||
|   } | ||||
| @ -266,7 +263,9 @@ export class RuntimeMetadataResolver { | ||||
|     return new cpl.CompileProviderMetadata({ | ||||
|       token: this.getTokenMetadata(provider.token), | ||||
|       useClass: isPresent(provider.useClass) ? this.getTypeMetadata(provider.useClass, null) : null, | ||||
|       useValue: isPresent(provider.useValue) ? this.getRuntimeIdentifier(provider.useValue) : null, | ||||
|       useValue: isPresent(provider.useValue) ? | ||||
|                     new cpl.CompileIdentifierMetadata({runtime: provider.useValue}) : | ||||
|                     null, | ||||
|       useFactory: isPresent(provider.useFactory) ? | ||||
|                       this.getFactoryMetadata(provider.useFactory, null) : | ||||
|                       null, | ||||
|  | ||||
| @ -23,3 +23,7 @@ export function splitAtColon(input: string, defaultValues: string[]): string[] { | ||||
|     return defaultValues; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function sanitizeIdentifier(name: string): string { | ||||
|   return StringWrapper.replaceAll(name, /\W/g, '_'); | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| import {isPresent, isBlank} from 'angular2/src/facade/lang'; | ||||
| import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; | ||||
| import {BaseException} from 'angular2/src/facade/exceptions'; | ||||
| 
 | ||||
| import * as o from '../output/output_ast'; | ||||
| import {Identifiers, identifierToken} from '../identifiers'; | ||||
| @ -47,7 +48,7 @@ export class CompileView implements NameResolver { | ||||
|   public dirtyParentQueriesMethod: CompileMethod; | ||||
|   public updateViewQueriesMethod: CompileMethod; | ||||
|   public detectChangesInInputsMethod: CompileMethod; | ||||
|   public detectChangesHostPropertiesMethod: CompileMethod; | ||||
|   public detectChangesRenderPropertiesMethod: CompileMethod; | ||||
|   public afterContentLifecycleCallbacksMethod: CompileMethod; | ||||
|   public afterViewLifecycleCallbacksMethod: CompileMethod; | ||||
|   public destroyMethod: CompileMethod; | ||||
| @ -78,7 +79,7 @@ export class CompileView implements NameResolver { | ||||
|     this.dirtyParentQueriesMethod = new CompileMethod(this); | ||||
|     this.updateViewQueriesMethod = new CompileMethod(this); | ||||
|     this.detectChangesInInputsMethod = new CompileMethod(this); | ||||
|     this.detectChangesHostPropertiesMethod = new CompileMethod(this); | ||||
|     this.detectChangesRenderPropertiesMethod = new CompileMethod(this); | ||||
| 
 | ||||
|     this.afterContentLifecycleCallbacksMethod = new CompileMethod(this); | ||||
|     this.afterViewLifecycleCallbacksMethod = new CompileMethod(this); | ||||
| @ -124,7 +125,18 @@ export class CompileView implements NameResolver { | ||||
|   } | ||||
| 
 | ||||
|   createPipe(name: string): o.Expression { | ||||
|     var pipeMeta: CompilePipeMetadata = this.pipeMetas.find((pipeMeta) => pipeMeta.name == name); | ||||
|     var pipeMeta: CompilePipeMetadata = null; | ||||
|     for (var i = this.pipeMetas.length - 1; i >= 0; i--) { | ||||
|       var localPipeMeta = this.pipeMetas[i]; | ||||
|       if (localPipeMeta.name == name) { | ||||
|         pipeMeta = localPipeMeta; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if (isBlank(pipeMeta)) { | ||||
|       throw new BaseException( | ||||
|           `Illegal state: Could not find pipe ${name} although the parser should have detected this error!`); | ||||
|     } | ||||
|     var pipeFieldName = pipeMeta.pure ? `_pipe_${name}` : `_pipe_${name}_${this.pipes.size}`; | ||||
|     var pipeExpr = this.pipes.get(pipeFieldName); | ||||
|     if (isBlank(pipeExpr)) { | ||||
|  | ||||
| @ -71,7 +71,7 @@ export function bindRenderText(boundText: BoundTextAst, compileNode: CompileNode | ||||
|   view.bindings.push(new CompileBinding(compileNode, boundText)); | ||||
|   var currValExpr = createCurrValueExpr(bindingIndex); | ||||
|   var valueField = createBindFieldExpr(bindingIndex); | ||||
|   view.detectChangesInInputsMethod.resetDebugInfo(compileNode.nodeIndex, boundText); | ||||
|   view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText); | ||||
| 
 | ||||
|   bind(view, currValExpr, valueField, boundText.value, o.THIS_EXPR.prop('context'), | ||||
|        [ | ||||
| @ -79,7 +79,7 @@ export function bindRenderText(boundText: BoundTextAst, compileNode: CompileNode | ||||
|              .callMethod('setText', [compileNode.renderNode, currValExpr]) | ||||
|              .toStmt() | ||||
|        ], | ||||
|        view.detectChangesInInputsMethod); | ||||
|        view.detectChangesRenderPropertiesMethod); | ||||
| } | ||||
| 
 | ||||
| function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: o.Expression, | ||||
| @ -89,7 +89,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: | ||||
|   boundProps.forEach((boundProp) => { | ||||
|     var bindingIndex = view.bindings.length; | ||||
|     view.bindings.push(new CompileBinding(compileElement, boundProp)); | ||||
|     view.detectChangesHostPropertiesMethod.resetDebugInfo(compileElement.nodeIndex, boundProp); | ||||
|     view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileElement.nodeIndex, boundProp); | ||||
|     var fieldExpr = createBindFieldExpr(bindingIndex); | ||||
|     var currValExpr = createCurrValueExpr(bindingIndex); | ||||
|     var renderMethod: string; | ||||
| @ -125,7 +125,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: | ||||
|             .toStmt()); | ||||
| 
 | ||||
|     bind(view, currValExpr, fieldExpr, boundProp.value, context, updateStmts, | ||||
|          view.detectChangesHostPropertiesMethod); | ||||
|          view.detectChangesRenderPropertiesMethod); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -538,8 +538,8 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] { | ||||
|   var stmts = []; | ||||
|   if (view.detectChangesInInputsMethod.isEmpty() && view.updateContentQueriesMethod.isEmpty() && | ||||
|       view.afterContentLifecycleCallbacksMethod.isEmpty() && | ||||
|       view.detectChangesHostPropertiesMethod.isEmpty() && view.updateViewQueriesMethod.isEmpty() && | ||||
|       view.afterViewLifecycleCallbacksMethod.isEmpty()) { | ||||
|       view.detectChangesRenderPropertiesMethod.isEmpty() && | ||||
|       view.updateViewQueriesMethod.isEmpty() && view.afterViewLifecycleCallbacksMethod.isEmpty()) { | ||||
|     return stmts; | ||||
|   } | ||||
|   ListWrapper.addAll(stmts, view.detectChangesInInputsMethod.finish()); | ||||
| @ -551,7 +551,7 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] { | ||||
|   if (afterContentStmts.length > 0) { | ||||
|     stmts.push(new o.IfStmt(o.not(DetectChangesVars.throwOnChange), afterContentStmts)); | ||||
|   } | ||||
|   ListWrapper.addAll(stmts, view.detectChangesHostPropertiesMethod.finish()); | ||||
|   ListWrapper.addAll(stmts, view.detectChangesRenderPropertiesMethod.finish()); | ||||
|   stmts.push(o.THIS_EXPR.callMethod('detectViewChildrenChanges', [DetectChangesVars.throwOnChange]) | ||||
|                  .toStmt()); | ||||
|   var afterViewStmts = | ||||
|  | ||||
							
								
								
									
										150
									
								
								modules/angular2/test/core/linker/regression_integration_spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								modules/angular2/test/core/linker/regression_integration_spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | ||||
| import { | ||||
|   AsyncTestCompleter, | ||||
|   beforeEach, | ||||
|   ddescribe, | ||||
|   xdescribe, | ||||
|   describe, | ||||
|   el, | ||||
|   dispatchEvent, | ||||
|   expect, | ||||
|   iit, | ||||
|   inject, | ||||
|   beforeEachProviders, | ||||
|   it, | ||||
|   xit, | ||||
|   containsRegexp, | ||||
|   stringifyElement, | ||||
|   TestComponentBuilder, | ||||
|   fakeAsync, | ||||
|   tick, | ||||
|   clearPendingTimers, | ||||
|   ComponentFixture | ||||
| } from 'angular2/testing_internal'; | ||||
| 
 | ||||
| import {IS_DART} from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| import { | ||||
|   Component, | ||||
|   Pipe, | ||||
|   PipeTransform, | ||||
|   provide, | ||||
|   ViewMetadata, | ||||
|   PLATFORM_PIPES, | ||||
|   OpaqueToken, | ||||
|   Injector | ||||
| } from 'angular2/core'; | ||||
| import {CompilerConfig} from 'angular2/compiler'; | ||||
| 
 | ||||
| export function main() { | ||||
|   if (IS_DART) { | ||||
|     declareTests(false); | ||||
|   } else { | ||||
|     describe('jit', () => { | ||||
|       beforeEachProviders( | ||||
|           () => [provide(CompilerConfig, {useValue: new CompilerConfig(true, false, true)})]); | ||||
|       declareTests(true); | ||||
|     }); | ||||
| 
 | ||||
|     describe('no jit', () => { | ||||
|       beforeEachProviders( | ||||
|           () => [provide(CompilerConfig, {useValue: new CompilerConfig(true, false, false)})]); | ||||
|       declareTests(false); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function declareTests(isJit: boolean) { | ||||
|   // Place to put reproductions for regressions
 | ||||
|   describe('regressions', () => { | ||||
| 
 | ||||
|     describe('platform pipes', () => { | ||||
|       beforeEachProviders(() => [provide(PLATFORM_PIPES, {useValue: [PlatformPipe], multi: true})]); | ||||
| 
 | ||||
|       it('should overwrite them by custom pipes', | ||||
|          inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { | ||||
|            tcb.overrideView( | ||||
|                   MyComp, new ViewMetadata({template: '{{true | somePipe}}', pipes: [CustomPipe]})) | ||||
|                .createAsync(MyComp) | ||||
|                .then((fixture) => { | ||||
|                  fixture.detectChanges(); | ||||
|                  expect(fixture.nativeElement).toHaveText('someCustomPipe'); | ||||
|                  async.done(); | ||||
|                }); | ||||
|          })); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     describe('providers', () => { | ||||
|       function createInjector(tcb: TestComponentBuilder, proviers: any[]): Promise<Injector> { | ||||
|         return tcb.overrideProviders(MyComp, [proviers]) | ||||
|             .createAsync(MyComp) | ||||
|             .then((fixture) => fixture.componentInstance.injector); | ||||
|       } | ||||
| 
 | ||||
|       it('should support providers with an OpaqueToken that contains a `.` in the name', | ||||
|          inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { | ||||
|            var token = new OpaqueToken('a.b'); | ||||
|            var tokenValue = 1; | ||||
|            createInjector(tcb, [provide(token, {useValue: tokenValue})]) | ||||
|                .then((injector: Injector) => { | ||||
|                  expect(injector.get(token)).toEqual(tokenValue); | ||||
|                  async.done(); | ||||
|                }); | ||||
|          })); | ||||
| 
 | ||||
|       it('should support providers with an anonymous function', | ||||
|          inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { | ||||
|            var token = () => true; | ||||
|            var tokenValue = 1; | ||||
|            createInjector(tcb, [provide(token, {useValue: tokenValue})]) | ||||
|                .then((injector: Injector) => { | ||||
|                  expect(injector.get(token)).toEqual(tokenValue); | ||||
|                  async.done(); | ||||
|                }); | ||||
|          })); | ||||
| 
 | ||||
|       it('should support providers with an OpaqueToken that has a StringMap as value', | ||||
|          inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { | ||||
|            var token1 = new OpaqueToken('someToken'); | ||||
|            var token2 = new OpaqueToken('someToken'); | ||||
|            var tokenValue1 = {'a': 1}; | ||||
|            var tokenValue2 = {'a': 1}; | ||||
|            createInjector( | ||||
|                tcb, | ||||
|                [provide(token1, {useValue: tokenValue1}), provide(token2, {useValue: tokenValue2})]) | ||||
|                .then((injector: Injector) => { | ||||
|                  expect(injector.get(token1)).toEqual(tokenValue1); | ||||
|                  expect(injector.get(token2)).toEqual(tokenValue2); | ||||
|                  async.done(); | ||||
|                }); | ||||
|          })); | ||||
|     }); | ||||
| 
 | ||||
|     it('should allow logging a previous elements class binding via interpolation', | ||||
|        inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { | ||||
|          tcb.overrideTemplate(MyComp, `<div [class.a]="true" #el>Class: {{el.className}}</div>`) | ||||
|              .createAsync(MyComp) | ||||
|              .then((fixture) => { | ||||
|                fixture.detectChanges(); | ||||
|                expect(fixture.nativeElement).toHaveText('Class: a'); | ||||
|                async.done(); | ||||
|              }); | ||||
|        })); | ||||
| 
 | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| @Component({selector: 'my-comp', template: ''}) | ||||
| class MyComp { | ||||
|   constructor(public injector: Injector) {} | ||||
| } | ||||
| 
 | ||||
| @Pipe({name: 'somePipe', pure: true}) | ||||
| class PlatformPipe implements PipeTransform { | ||||
|   transform(value: any, args: any[]): any { return 'somePlatformPipe'; } | ||||
| } | ||||
| 
 | ||||
| @Pipe({name: 'somePipe', pure: true}) | ||||
| class CustomPipe implements PipeTransform { | ||||
|   transform(value: any, args: any[]): any { return 'someCustomPipe'; } | ||||
| } | ||||
| @ -88,6 +88,8 @@ const ALL_PIPES = CONST_EXPR([ | ||||
|   forwardRef(() => PipeNeedsService), | ||||
|   forwardRef(() => PurePipe), | ||||
|   forwardRef(() => ImpurePipe), | ||||
|   forwardRef(() => DuplicatePipe1), | ||||
|   forwardRef(() => DuplicatePipe2), | ||||
| ]); | ||||
| 
 | ||||
| @Directive({selector: '[simpleDirective]'}) | ||||
| @ -254,6 +256,15 @@ export class PipeNeedsService implements PipeTransform { | ||||
|   transform(value: any, args: any[] = null): any { return this; } | ||||
| } | ||||
| 
 | ||||
| @Pipe({name: 'duplicatePipe'}) | ||||
| export class DuplicatePipe1 implements PipeTransform { | ||||
|   transform(value: any, args: any[] = null): any { return this; } | ||||
| } | ||||
| 
 | ||||
| @Pipe({name: 'duplicatePipe'}) | ||||
| export class DuplicatePipe2 implements PipeTransform { | ||||
|   transform(value: any, args: any[] = null): any { return this; } | ||||
| } | ||||
| 
 | ||||
| @Component({selector: 'root'}) | ||||
| class TestComp { | ||||
| @ -628,6 +639,11 @@ export function main() { | ||||
|            expect(el.children[0].inject(SimpleDirective).value.service).toEqual('pipeService'); | ||||
|          })); | ||||
| 
 | ||||
|       it('should overwrite pipes with later entry in the pipes array', fakeAsync(() => { | ||||
|            var el = createComp('<div [simpleDirective]="true | duplicatePipe"></div>', tcb); | ||||
|            expect(el.children[0].inject(SimpleDirective).value).toBeAnInstanceOf(DuplicatePipe2); | ||||
|          })); | ||||
| 
 | ||||
|       it('should inject ChangeDetectorRef into pipes', fakeAsync(() => { | ||||
|            var el = createComp( | ||||
|                '<div [simpleDirective]="true | pipeNeedsChangeDetectorRef" directiveNeedsChangeDetectorRef></div>', | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user