Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2f70457

Browse files
committed
fix(core): various minor compiler fixes
Closes angular#8162
1 parent 9889c21 commit 2f70457

File tree

8 files changed

+216
-37
lines changed

8 files changed

+216
-37
lines changed

modules/angular2/src/compiler/output/output_jit.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import * as o from './output_ast';
1010
import {EmitterVisitorContext} from './abstract_emitter';
1111
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
12+
import {sanitizeIdentifier} from '../util';
1213

1314
export function jitStatements(sourceUrl: string, statements: o.Statement[],
1415
resultVar: string): any {
@@ -36,13 +37,10 @@ class JitEmitterVisitor extends AbstractJsEmitterVisitor {
3637
if (id === -1) {
3738
id = this._evalArgValues.length;
3839
this._evalArgValues.push(value);
39-
this._evalArgNames.push(sanitizeJitArgName(`jit_${ast.value.name}${id}`));
40+
var name = isPresent(ast.value.name) ? sanitizeIdentifier(ast.value.name) : 'val';
41+
this._evalArgNames.push(sanitizeIdentifier(`jit_${name}${id}`));
4042
}
4143
ctx.print(this._evalArgNames[id]);
4244
return null;
4345
}
4446
}
45-
46-
function sanitizeJitArgName(name: string): string {
47-
return StringWrapper.replaceAll(name, /[\.\/]/g, '_');
48-
}

modules/angular2/src/compiler/runtime_metadata.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/metadata
2424
import {reflector} from 'angular2/src/core/reflection/reflection';
2525
import {Injectable, Inject, Optional} from 'angular2/src/core/di';
2626
import {PLATFORM_DIRECTIVES, PLATFORM_PIPES} from 'angular2/src/core/platform_directives_and_pipes';
27-
import {MODULE_SUFFIX} from './util';
27+
import {MODULE_SUFFIX, sanitizeIdentifier} from './util';
2828
import {assertArrayOfStrings} from './assertions';
2929
import {getUrlScheme} from 'angular2/src/compiler/url_resolver';
3030
import {Provider} from 'angular2/src/core/di/provider';
@@ -52,20 +52,18 @@ export class RuntimeMetadataResolver {
5252
@Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[],
5353
@Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Type[]) {}
5454

55-
/**
56-
* Wrap the stringify method to avoid naming things `function (arg1...) {`
57-
*/
58-
private sanitizeName(obj: any): string {
59-
let result = StringWrapper.replaceAll(stringify(obj), /[\s-]/g, '_');
60-
if (result.indexOf('(') < 0) {
61-
return result;
62-
}
63-
let found = this._anonymousTypes.get(obj);
64-
if (isBlank(found)) {
65-
this._anonymousTypes.set(obj, this._anonymousTypeIndex++);
66-
found = this._anonymousTypes.get(obj);
55+
private sanitizeTokenName(token: any): string {
56+
let identifier = stringify(token);
57+
if (identifier.indexOf('(') >= 0) {
58+
// case: anonymous functions!
59+
let found = this._anonymousTypes.get(token);
60+
if (isBlank(found)) {
61+
this._anonymousTypes.set(token, this._anonymousTypeIndex++);
62+
found = this._anonymousTypes.get(token);
63+
}
64+
identifier = `anonymous_token_${found}_`;
6765
}
68-
return `anonymous_type_${found}_`;
66+
return sanitizeIdentifier(identifier);
6967
}
7068

7169
getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
@@ -130,7 +128,7 @@ export class RuntimeMetadataResolver {
130128

131129
getTypeMetadata(type: Type, moduleUrl: string): cpl.CompileTypeMetadata {
132130
return new cpl.CompileTypeMetadata({
133-
name: this.sanitizeName(type),
131+
name: this.sanitizeTokenName(type),
134132
moduleUrl: moduleUrl,
135133
runtime: type,
136134
diDeps: this.getDependenciesMetadata(type, null)
@@ -139,7 +137,7 @@ export class RuntimeMetadataResolver {
139137

140138
getFactoryMetadata(factory: Function, moduleUrl: string): cpl.CompileFactoryMetadata {
141139
return new cpl.CompileFactoryMetadata({
142-
name: this.sanitizeName(factory),
140+
name: this.sanitizeTokenName(factory),
143141
moduleUrl: moduleUrl,
144142
runtime: factory,
145143
diDeps: this.getDependenciesMetadata(factory, null)
@@ -227,17 +225,16 @@ export class RuntimeMetadataResolver {
227225
});
228226
}
229227

230-
getRuntimeIdentifier(value: any): cpl.CompileIdentifierMetadata {
231-
return new cpl.CompileIdentifierMetadata({runtime: value, name: this.sanitizeName(value)});
232-
}
233-
234228
getTokenMetadata(token: any): cpl.CompileTokenMetadata {
235229
token = resolveForwardRef(token);
236230
var compileToken;
237231
if (isString(token)) {
238232
compileToken = new cpl.CompileTokenMetadata({value: token});
239233
} else {
240-
compileToken = new cpl.CompileTokenMetadata({identifier: this.getRuntimeIdentifier(token)});
234+
compileToken = new cpl.CompileTokenMetadata({
235+
identifier: new cpl.CompileIdentifierMetadata(
236+
{runtime: token, name: this.sanitizeTokenName(token)})
237+
});
241238
}
242239
return compileToken;
243240
}
@@ -266,7 +263,9 @@ export class RuntimeMetadataResolver {
266263
return new cpl.CompileProviderMetadata({
267264
token: this.getTokenMetadata(provider.token),
268265
useClass: isPresent(provider.useClass) ? this.getTypeMetadata(provider.useClass, null) : null,
269-
useValue: isPresent(provider.useValue) ? this.getRuntimeIdentifier(provider.useValue) : null,
266+
useValue: isPresent(provider.useValue) ?
267+
new cpl.CompileIdentifierMetadata({runtime: provider.useValue}) :
268+
null,
270269
useFactory: isPresent(provider.useFactory) ?
271270
this.getFactoryMetadata(provider.useFactory, null) :
272271
null,

modules/angular2/src/compiler/util.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ export function splitAtColon(input: string, defaultValues: string[]): string[] {
2323
return defaultValues;
2424
}
2525
}
26+
27+
export function sanitizeIdentifier(name: string): string {
28+
return StringWrapper.replaceAll(name, /\W/g, '_');
29+
}

modules/angular2/src/compiler/view_compiler/compile_view.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {isPresent, isBlank} from 'angular2/src/facade/lang';
22
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
3+
import {BaseException} from 'angular2/src/facade/exceptions';
34

45
import * as o from '../output/output_ast';
56
import {Identifiers, identifierToken} from '../identifiers';
@@ -47,7 +48,7 @@ export class CompileView implements NameResolver {
4748
public dirtyParentQueriesMethod: CompileMethod;
4849
public updateViewQueriesMethod: CompileMethod;
4950
public detectChangesInInputsMethod: CompileMethod;
50-
public detectChangesHostPropertiesMethod: CompileMethod;
51+
public detectChangesRenderPropertiesMethod: CompileMethod;
5152
public afterContentLifecycleCallbacksMethod: CompileMethod;
5253
public afterViewLifecycleCallbacksMethod: CompileMethod;
5354
public destroyMethod: CompileMethod;
@@ -78,7 +79,7 @@ export class CompileView implements NameResolver {
7879
this.dirtyParentQueriesMethod = new CompileMethod(this);
7980
this.updateViewQueriesMethod = new CompileMethod(this);
8081
this.detectChangesInInputsMethod = new CompileMethod(this);
81-
this.detectChangesHostPropertiesMethod = new CompileMethod(this);
82+
this.detectChangesRenderPropertiesMethod = new CompileMethod(this);
8283

8384
this.afterContentLifecycleCallbacksMethod = new CompileMethod(this);
8485
this.afterViewLifecycleCallbacksMethod = new CompileMethod(this);
@@ -124,7 +125,18 @@ export class CompileView implements NameResolver {
124125
}
125126

126127
createPipe(name: string): o.Expression {
127-
var pipeMeta: CompilePipeMetadata = this.pipeMetas.find((pipeMeta) => pipeMeta.name == name);
128+
var pipeMeta: CompilePipeMetadata = null;
129+
for (var i = this.pipeMetas.length - 1; i >= 0; i--) {
130+
var localPipeMeta = this.pipeMetas[i];
131+
if (localPipeMeta.name == name) {
132+
pipeMeta = localPipeMeta;
133+
break;
134+
}
135+
}
136+
if (isBlank(pipeMeta)) {
137+
throw new BaseException(
138+
`Illegal state: Could not find pipe ${name} although the parser should have detected this error!`);
139+
}
128140
var pipeFieldName = pipeMeta.pure ? `_pipe_${name}` : `_pipe_${name}_${this.pipes.size}`;
129141
var pipeExpr = this.pipes.get(pipeFieldName);
130142
if (isBlank(pipeExpr)) {

modules/angular2/src/compiler/view_compiler/property_binder.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ export function bindRenderText(boundText: BoundTextAst, compileNode: CompileNode
7171
view.bindings.push(new CompileBinding(compileNode, boundText));
7272
var currValExpr = createCurrValueExpr(bindingIndex);
7373
var valueField = createBindFieldExpr(bindingIndex);
74-
view.detectChangesInInputsMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
74+
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
7575

7676
bind(view, currValExpr, valueField, boundText.value, o.THIS_EXPR.prop('context'),
7777
[
7878
o.THIS_EXPR.prop('renderer')
7979
.callMethod('setText', [compileNode.renderNode, currValExpr])
8080
.toStmt()
8181
],
82-
view.detectChangesInInputsMethod);
82+
view.detectChangesRenderPropertiesMethod);
8383
}
8484

8585
function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: o.Expression,
@@ -89,7 +89,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
8989
boundProps.forEach((boundProp) => {
9090
var bindingIndex = view.bindings.length;
9191
view.bindings.push(new CompileBinding(compileElement, boundProp));
92-
view.detectChangesHostPropertiesMethod.resetDebugInfo(compileElement.nodeIndex, boundProp);
92+
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileElement.nodeIndex, boundProp);
9393
var fieldExpr = createBindFieldExpr(bindingIndex);
9494
var currValExpr = createCurrValueExpr(bindingIndex);
9595
var renderMethod: string;
@@ -125,7 +125,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
125125
.toStmt());
126126

127127
bind(view, currValExpr, fieldExpr, boundProp.value, context, updateStmts,
128-
view.detectChangesHostPropertiesMethod);
128+
view.detectChangesRenderPropertiesMethod);
129129
});
130130
}
131131

modules/angular2/src/compiler/view_compiler/view_builder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] {
538538
var stmts = [];
539539
if (view.detectChangesInInputsMethod.isEmpty() && view.updateContentQueriesMethod.isEmpty() &&
540540
view.afterContentLifecycleCallbacksMethod.isEmpty() &&
541-
view.detectChangesHostPropertiesMethod.isEmpty() && view.updateViewQueriesMethod.isEmpty() &&
542-
view.afterViewLifecycleCallbacksMethod.isEmpty()) {
541+
view.detectChangesRenderPropertiesMethod.isEmpty() &&
542+
view.updateViewQueriesMethod.isEmpty() && view.afterViewLifecycleCallbacksMethod.isEmpty()) {
543543
return stmts;
544544
}
545545
ListWrapper.addAll(stmts, view.detectChangesInInputsMethod.finish());
@@ -551,7 +551,7 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] {
551551
if (afterContentStmts.length > 0) {
552552
stmts.push(new o.IfStmt(o.not(DetectChangesVars.throwOnChange), afterContentStmts));
553553
}
554-
ListWrapper.addAll(stmts, view.detectChangesHostPropertiesMethod.finish());
554+
ListWrapper.addAll(stmts, view.detectChangesRenderPropertiesMethod.finish());
555555
stmts.push(o.THIS_EXPR.callMethod('detectViewChildrenChanges', [DetectChangesVars.throwOnChange])
556556
.toStmt());
557557
var afterViewStmts =
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import {
2+
AsyncTestCompleter,
3+
beforeEach,
4+
ddescribe,
5+
xdescribe,
6+
describe,
7+
el,
8+
dispatchEvent,
9+
expect,
10+
iit,
11+
inject,
12+
beforeEachProviders,
13+
it,
14+
xit,
15+
containsRegexp,
16+
stringifyElement,
17+
TestComponentBuilder,
18+
fakeAsync,
19+
tick,
20+
clearPendingTimers,
21+
ComponentFixture
22+
} from 'angular2/testing_internal';
23+
24+
import {IS_DART} from 'angular2/src/facade/lang';
25+
26+
import {
27+
Component,
28+
Pipe,
29+
PipeTransform,
30+
provide,
31+
ViewMetadata,
32+
PLATFORM_PIPES,
33+
OpaqueToken,
34+
Injector
35+
} from 'angular2/core';
36+
import {CompilerConfig} from 'angular2/compiler';
37+
38+
export function main() {
39+
if (IS_DART) {
40+
declareTests(false);
41+
} else {
42+
describe('jit', () => {
43+
beforeEachProviders(
44+
() => [provide(CompilerConfig, {useValue: new CompilerConfig(true, false, true)})]);
45+
declareTests(true);
46+
});
47+
48+
describe('no jit', () => {
49+
beforeEachProviders(
50+
() => [provide(CompilerConfig, {useValue: new CompilerConfig(true, false, false)})]);
51+
declareTests(false);
52+
});
53+
}
54+
}
55+
56+
function declareTests(isJit: boolean) {
57+
// Place to put reproductions for regressions
58+
describe('regressions', () => {
59+
60+
describe('platform pipes', () => {
61+
beforeEachProviders(() => [provide(PLATFORM_PIPES, {useValue: [PlatformPipe], multi: true})]);
62+
63+
it('should overwrite them by custom pipes',
64+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
65+
tcb.overrideView(
66+
MyComp, new ViewMetadata({template: '{{true | somePipe}}', pipes: [CustomPipe]}))
67+
.createAsync(MyComp)
68+
.then((fixture) => {
69+
fixture.detectChanges();
70+
expect(fixture.nativeElement).toHaveText('someCustomPipe');
71+
async.done();
72+
});
73+
}));
74+
75+
});
76+
77+
describe('providers', () => {
78+
function createInjector(tcb: TestComponentBuilder, proviers: any[]): Promise<Injector> {
79+
return tcb.overrideProviders(MyComp, [proviers])
80+
.createAsync(MyComp)
81+
.then((fixture) => fixture.componentInstance.injector);
82+
}
83+
84+
it('should support providers with an OpaqueToken that contains a `.` in the name',
85+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
86+
var token = new OpaqueToken('a.b');
87+
var tokenValue = 1;
88+
createInjector(tcb, [provide(token, {useValue: tokenValue})])
89+
.then((injector: Injector) => {
90+
expect(injector.get(token)).toEqual(tokenValue);
91+
async.done();
92+
});
93+
}));
94+
95+
it('should support providers with an anonymous function',
96+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
97+
var token = () => true;
98+
var tokenValue = 1;
99+
createInjector(tcb, [provide(token, {useValue: tokenValue})])
100+
.then((injector: Injector) => {
101+
expect(injector.get(token)).toEqual(tokenValue);
102+
async.done();
103+
});
104+
}));
105+
106+
it('should support providers with an OpaqueToken that has a StringMap as value',
107+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
108+
var token1 = new OpaqueToken('someToken');
109+
var token2 = new OpaqueToken('someToken');
110+
var tokenValue1 = {'a': 1};
111+
var tokenValue2 = {'a': 1};
112+
createInjector(
113+
tcb,
114+
[provide(token1, {useValue: tokenValue1}), provide(token2, {useValue: tokenValue2})])
115+
.then((injector: Injector) => {
116+
expect(injector.get(token1)).toEqual(tokenValue1);
117+
expect(injector.get(token2)).toEqual(tokenValue2);
118+
async.done();
119+
});
120+
}));
121+
});
122+
123+
it('should allow logging a previous elements class binding via interpolation',
124+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
125+
tcb.overrideTemplate(MyComp, `<div [class.a]="true" #el>Class: {{el.className}}</div>`)
126+
.createAsync(MyComp)
127+
.then((fixture) => {
128+
fixture.detectChanges();
129+
expect(fixture.nativeElement).toHaveText('Class: a');
130+
async.done();
131+
});
132+
}));
133+
134+
});
135+
}
136+
137+
@Component({selector: 'my-comp', template: ''})
138+
class MyComp {
139+
constructor(public injector: Injector) {}
140+
}
141+
142+
@Pipe({name: 'somePipe', pure: true})
143+
class PlatformPipe implements PipeTransform {
144+
transform(value: any, args: any[]): any { return 'somePlatformPipe'; }
145+
}
146+
147+
@Pipe({name: 'somePipe', pure: true})
148+
class CustomPipe implements PipeTransform {
149+
transform(value: any, args: any[]): any { return 'someCustomPipe'; }
150+
}

0 commit comments

Comments
 (0)