fix(compiler): properly implement pure pipes and change pipe syntax
Pure pipes as well as arrays and maps are implemented via proxy functions. This is faster than the previous implementation and also generates less code. BREAKING CHANGE: - pipes now take a variable number of arguments, and not an array that contains all arguments.
This commit is contained in:
@@ -1,13 +1,6 @@
|
||||
import {isBlank, isPresent, isPromise, CONST} from 'angular2/src/facade/lang';
|
||||
import {ObservableWrapper, Observable, EventEmitter} from 'angular2/src/facade/async';
|
||||
import {
|
||||
Pipe,
|
||||
Injectable,
|
||||
ChangeDetectorRef,
|
||||
OnDestroy,
|
||||
PipeTransform,
|
||||
WrappedValue
|
||||
} from 'angular2/core';
|
||||
import {Pipe, Injectable, ChangeDetectorRef, OnDestroy, WrappedValue} from 'angular2/core';
|
||||
|
||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
|
||||
@@ -55,7 +48,7 @@ var __unused: Promise<any>; // avoid unused import when Promise union types are
|
||||
*/
|
||||
@Pipe({name: 'async', pure: false})
|
||||
@Injectable()
|
||||
export class AsyncPipe implements PipeTransform, OnDestroy {
|
||||
export class AsyncPipe implements OnDestroy {
|
||||
/** @internal */
|
||||
_latestValue: Object = null;
|
||||
/** @internal */
|
||||
@@ -76,7 +69,7 @@ export class AsyncPipe implements PipeTransform, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
transform(obj: Observable<any>| Promise<any>| EventEmitter<any>, args?: any[]): any {
|
||||
transform(obj: Observable<any>| Promise<any>| EventEmitter<any>): any {
|
||||
if (isBlank(this._obj)) {
|
||||
if (isPresent(obj)) {
|
||||
this._subscribe(obj);
|
||||
|
||||
@@ -101,14 +101,13 @@ export class DatePipe implements PipeTransform {
|
||||
};
|
||||
|
||||
|
||||
transform(value: any, args: any[]): string {
|
||||
transform(value: any, pattern: string = 'mediumDate'): string {
|
||||
if (isBlank(value)) return null;
|
||||
|
||||
if (!this.supports(value)) {
|
||||
throw new InvalidPipeArgumentException(DatePipe, value);
|
||||
}
|
||||
|
||||
var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
|
||||
if (isNumber(value)) {
|
||||
value = DateWrapper.fromMillis(value);
|
||||
}
|
||||
|
||||
@@ -45,10 +45,9 @@ var interpolationExp: RegExp = RegExpWrapper.create('#');
|
||||
@Pipe({name: 'i18nPlural', pure: true})
|
||||
@Injectable()
|
||||
export class I18nPluralPipe implements PipeTransform {
|
||||
transform(value: number, args: any[] = null): string {
|
||||
transform(value: number, pluralMap: {[count: string]: string}): string {
|
||||
var key: string;
|
||||
var valueStr: string;
|
||||
var pluralMap: {[count: string]: string} = <{[count: string]: string}>(args[0]);
|
||||
|
||||
if (!isStringMap(pluralMap)) {
|
||||
throw new InvalidPipeArgumentException(I18nPluralPipe, pluralMap);
|
||||
|
||||
@@ -36,8 +36,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@Pipe({name: 'i18nSelect', pure: true})
|
||||
@Injectable()
|
||||
export class I18nSelectPipe implements PipeTransform {
|
||||
transform(value: string, args: any[] = null): string {
|
||||
var mapping: {[key: string]: string} = <{[count: string]: string}>(args[0]);
|
||||
transform(value: string, mapping: {[key: string]: string}): string {
|
||||
if (!isStringMap(mapping)) {
|
||||
throw new InvalidPipeArgumentException(I18nSelectPipe, mapping);
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ import {Injectable, PipeTransform, WrappedValue, Pipe} from 'angular2/core';
|
||||
@Pipe({name: 'json', pure: false})
|
||||
@Injectable()
|
||||
export class JsonPipe implements PipeTransform {
|
||||
transform(value: any, args: any[] = null): string { return Json.stringify(value); }
|
||||
transform(value: any): string { return Json.stringify(value); }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@Pipe({name: 'lowercase'})
|
||||
@Injectable()
|
||||
export class LowerCasePipe implements PipeTransform {
|
||||
transform(value: string, args: any[] = null): string {
|
||||
transform(value: string): string {
|
||||
if (isBlank(value)) return value;
|
||||
if (!isString(value)) {
|
||||
throw new InvalidPipeArgumentException(LowerCasePipe, value);
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
import {NumberFormatter, NumberFormatStyle} from 'angular2/src/facade/intl';
|
||||
import {Injectable, PipeTransform, WrappedValue, Pipe} from 'angular2/core';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
|
||||
@@ -87,8 +86,7 @@ export class NumberPipe {
|
||||
@Pipe({name: 'number'})
|
||||
@Injectable()
|
||||
export class DecimalPipe extends NumberPipe implements PipeTransform {
|
||||
transform(value: any, args: any[]): string {
|
||||
var digits: string = ListWrapper.first(args);
|
||||
transform(value: any, digits: string = null): string {
|
||||
return NumberPipe._format(value, NumberFormatStyle.Decimal, digits);
|
||||
}
|
||||
}
|
||||
@@ -113,8 +111,7 @@ export class DecimalPipe extends NumberPipe implements PipeTransform {
|
||||
@Pipe({name: 'percent'})
|
||||
@Injectable()
|
||||
export class PercentPipe extends NumberPipe implements PipeTransform {
|
||||
transform(value: any, args: any[]): string {
|
||||
var digits: string = ListWrapper.first(args);
|
||||
transform(value: any, digits: string = null): string {
|
||||
return NumberPipe._format(value, NumberFormatStyle.Percent, digits);
|
||||
}
|
||||
}
|
||||
@@ -143,10 +140,8 @@ export class PercentPipe extends NumberPipe implements PipeTransform {
|
||||
@Pipe({name: 'currency'})
|
||||
@Injectable()
|
||||
export class CurrencyPipe extends NumberPipe implements PipeTransform {
|
||||
transform(value: any, args: any[]): string {
|
||||
var currencyCode: string = isPresent(args) && args.length > 0 ? args[0] : 'USD';
|
||||
var symbolDisplay: boolean = isPresent(args) && args.length > 1 ? args[1] : false;
|
||||
var digits: string = isPresent(args) && args.length > 2 ? args[2] : null;
|
||||
transform(value: any, currencyCode: string = 'USD', symbolDisplay: boolean = false,
|
||||
digits: string = null): string {
|
||||
return NumberPipe._format(value, NumberFormatStyle.Currency, digits, currencyCode,
|
||||
symbolDisplay);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
RegExpWrapper,
|
||||
StringWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
|
||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
|
||||
@@ -39,11 +38,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@Pipe({name: 'replace'})
|
||||
@Injectable()
|
||||
export class ReplacePipe implements PipeTransform {
|
||||
transform(value: any, args: any[]): any {
|
||||
if (isBlank(args) || args.length !== 2) {
|
||||
throw new BaseException('ReplacePipe requires two arguments');
|
||||
}
|
||||
|
||||
transform(value: any, pattern: string | RegExp, replacement: Function | string): any {
|
||||
if (isBlank(value)) {
|
||||
return value;
|
||||
}
|
||||
@@ -53,9 +48,6 @@ export class ReplacePipe implements PipeTransform {
|
||||
}
|
||||
|
||||
var input = value.toString();
|
||||
var pattern = args[0];
|
||||
var replacement = args[1];
|
||||
|
||||
|
||||
if (!this._supportedPattern(pattern)) {
|
||||
throw new InvalidPipeArgumentException(ReplacePipe, pattern);
|
||||
@@ -67,16 +59,16 @@ export class ReplacePipe implements PipeTransform {
|
||||
// var rgx = pattern instanceof RegExp ? pattern : RegExpWrapper.create(pattern);
|
||||
|
||||
if (isFunction(replacement)) {
|
||||
var rgxPattern = isString(pattern) ? RegExpWrapper.create(pattern) : pattern;
|
||||
var rgxPattern = isString(pattern) ? RegExpWrapper.create(<string>pattern) : <RegExp>pattern;
|
||||
|
||||
return StringWrapper.replaceAllMapped(input, rgxPattern, replacement);
|
||||
return StringWrapper.replaceAllMapped(input, rgxPattern, <Function>replacement);
|
||||
}
|
||||
if (pattern instanceof RegExp) {
|
||||
// use the replaceAll variant
|
||||
return StringWrapper.replaceAll(input, pattern, replacement);
|
||||
return StringWrapper.replaceAll(input, pattern, <string>replacement);
|
||||
}
|
||||
|
||||
return StringWrapper.replace(input, pattern, replacement);
|
||||
return StringWrapper.replace(input, <string>pattern, <string>replacement);
|
||||
}
|
||||
|
||||
private _supportedInput(input: any): boolean { return isString(input) || isNumber(input); }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {isBlank, isString, isArray, StringWrapper, CONST} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {Injectable, PipeTransform, WrappedValue, Pipe} from 'angular2/core';
|
||||
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@@ -59,16 +58,11 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@Pipe({name: 'slice', pure: false})
|
||||
@Injectable()
|
||||
export class SlicePipe implements PipeTransform {
|
||||
transform(value: any, args: any[] = null): any {
|
||||
if (isBlank(args) || args.length == 0) {
|
||||
throw new BaseException('Slice pipe requires one argument');
|
||||
}
|
||||
transform(value: any, start: number, end: number = null): any {
|
||||
if (!this.supports(value)) {
|
||||
throw new InvalidPipeArgumentException(SlicePipe, value);
|
||||
}
|
||||
if (isBlank(value)) return value;
|
||||
var start: number = args[0];
|
||||
var end: number = args.length > 1 ? args[1] : null;
|
||||
if (isString(value)) {
|
||||
return StringWrapper.slice(value, start, end);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
|
||||
@Pipe({name: 'uppercase'})
|
||||
@Injectable()
|
||||
export class UpperCasePipe implements PipeTransform {
|
||||
transform(value: string, args: any[] = null): string {
|
||||
transform(value: string): string {
|
||||
if (isBlank(value)) return value;
|
||||
if (!isString(value)) {
|
||||
throw new InvalidPipeArgumentException(UpperCasePipe, value);
|
||||
|
||||
@@ -5,7 +5,18 @@ import {
|
||||
ViewUtils,
|
||||
flattenNestedViewRenderNodes,
|
||||
interpolate,
|
||||
checkBinding
|
||||
checkBinding,
|
||||
castByValue,
|
||||
pureProxy1,
|
||||
pureProxy2,
|
||||
pureProxy3,
|
||||
pureProxy4,
|
||||
pureProxy5,
|
||||
pureProxy6,
|
||||
pureProxy7,
|
||||
pureProxy8,
|
||||
pureProxy9,
|
||||
pureProxy10
|
||||
} from 'angular2/src/core/linker/view_utils';
|
||||
import {
|
||||
uninitialized,
|
||||
@@ -59,6 +70,7 @@ var impFlattenNestedViewRenderNodes = flattenNestedViewRenderNodes;
|
||||
var impDevModeEqual = devModeEqual;
|
||||
var impInterpolate = interpolate;
|
||||
var impCheckBinding = checkBinding;
|
||||
var impCastByValue = castByValue;
|
||||
|
||||
export class Identifiers {
|
||||
static ViewUtils = new CompileIdentifierMetadata({
|
||||
@@ -162,6 +174,31 @@ export class Identifiers {
|
||||
{name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: impDevModeEqual});
|
||||
static interpolate = new CompileIdentifierMetadata(
|
||||
{name: 'interpolate', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: impInterpolate});
|
||||
static castByValue = new CompileIdentifierMetadata(
|
||||
{name: 'castByValue', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: impCastByValue});
|
||||
static pureProxies = [
|
||||
null,
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy1}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy2}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy3', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy3}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy4}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy5', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy5}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy6', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy6}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy7', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy7}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy8}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy9', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy9}),
|
||||
new CompileIdentifierMetadata(
|
||||
{name: 'pureProxy10', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy10}),
|
||||
];
|
||||
}
|
||||
|
||||
export function identifierToken(identifier: CompileIdentifierMetadata): CompileTokenMetadata {
|
||||
|
||||
@@ -197,6 +197,11 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
|
||||
var name = expr.name;
|
||||
if (isPresent(expr.builtin)) {
|
||||
name = this.getBuiltinMethodName(expr.builtin);
|
||||
if (isBlank(name)) {
|
||||
// some builtins just mean to skip the call.
|
||||
// e.g. `bind` in Dart.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
ctx.print(`.${name}(`);
|
||||
this.visitAllExpressions(expr.args, ctx, `,`);
|
||||
|
||||
@@ -153,6 +153,9 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'subscribe';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = 'bind';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
|
||||
@@ -213,6 +213,9 @@ class _DartEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisito
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'listen';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = null;
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ export class InterpretiveAppViewInstanceFactory implements InstanceFactory {
|
||||
class _InterpretiveAppView extends AppView<any> implements DynamicInstance {
|
||||
constructor(args: any[], public props: Map<string, any>, public getters: Map<string, Function>,
|
||||
public methods: Map<string, Function>) {
|
||||
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9],
|
||||
args[10]);
|
||||
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
|
||||
}
|
||||
createInternal(rootSelector: string | any): AppElement {
|
||||
var m = this.methods.get('createInternal');
|
||||
|
||||
@@ -244,7 +244,8 @@ export class WritePropExpr extends Expression {
|
||||
|
||||
export enum BuiltinMethod {
|
||||
ConcatArray,
|
||||
SubscribeObservable
|
||||
SubscribeObservable,
|
||||
bind
|
||||
}
|
||||
|
||||
export class InvokeMethodExpr extends Expression {
|
||||
|
||||
@@ -187,6 +187,13 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
result = ObservableWrapper.subscribe(receiver, args[0]);
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
if (IS_DART) {
|
||||
result = receiver;
|
||||
} else {
|
||||
result = receiver.bind(args[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method ${expr.builtin}`);
|
||||
}
|
||||
@@ -331,6 +338,8 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
result = di.props.get(ast.name);
|
||||
} else if (di.getters.has(ast.name)) {
|
||||
result = di.getters.get(ast.name)();
|
||||
} else if (di.methods.has(ast.name)) {
|
||||
result = di.methods.get(ast.name);
|
||||
} else {
|
||||
result = reflector.getter(ast.name)(receiver);
|
||||
}
|
||||
|
||||
@@ -287,6 +287,9 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'subscribe';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = 'bind';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
|
||||
@@ -324,7 +324,6 @@ export class CompileElement extends CompileNode {
|
||||
private _getDependency(requestingProviderType: ProviderAstType,
|
||||
dep: CompileDiDependencyMetadata): o.Expression {
|
||||
var currElement: CompileElement = this;
|
||||
var currView = currElement.view;
|
||||
var result = null;
|
||||
if (dep.isValue) {
|
||||
result = o.literal(dep.value);
|
||||
@@ -332,14 +331,9 @@ export class CompileElement extends CompileNode {
|
||||
if (isBlank(result) && !dep.isSkipSelf) {
|
||||
result = this._getLocalDependency(requestingProviderType, dep);
|
||||
}
|
||||
var resultViewPath = [];
|
||||
// check parent elements
|
||||
while (isBlank(result) && !currElement.parent.isNull()) {
|
||||
currElement = currElement.parent;
|
||||
while (currElement.view !== currView && currView != null) {
|
||||
currView = currView.declarationElement.view;
|
||||
resultViewPath.push(currView);
|
||||
}
|
||||
result = currElement._getLocalDependency(ProviderAstType.PublicService,
|
||||
new CompileDiDependencyMetadata({token: dep.token}));
|
||||
}
|
||||
@@ -350,7 +344,7 @@ export class CompileElement extends CompileNode {
|
||||
if (isBlank(result)) {
|
||||
result = o.NULL_EXPR;
|
||||
}
|
||||
return getPropertyInView(result, resultViewPath);
|
||||
return getPropertyInView(result, this.view, currElement.view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import {isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import * as o from '../output/output_ast';
|
||||
import {CompileView} from './compile_view';
|
||||
import {CompilePipeMetadata} from '../compile_metadata';
|
||||
import {Identifiers, identifierToken} from '../identifiers';
|
||||
import {injectFromViewParentInjector, createPureProxy, getPropertyInView} from './util';
|
||||
|
||||
class _PurePipeProxy {
|
||||
constructor(public instance: o.ReadPropExpr, public argCount: number) {}
|
||||
}
|
||||
|
||||
export class CompilePipe {
|
||||
meta: CompilePipeMetadata;
|
||||
instance: o.ReadPropExpr;
|
||||
private _purePipeProxies: _PurePipeProxy[] = [];
|
||||
|
||||
constructor(public view: CompileView, name: string) {
|
||||
this.meta = _findPipeMeta(view, name);
|
||||
this.instance = o.THIS_EXPR.prop(`_pipe_${name}_${view.pipeCount++}`);
|
||||
}
|
||||
|
||||
get pure(): boolean { return this.meta.pure; }
|
||||
|
||||
create(): void {
|
||||
var deps = this.meta.type.diDeps.map((diDep) => {
|
||||
if (diDep.token.equalsTo(identifierToken(Identifiers.ChangeDetectorRef))) {
|
||||
return o.THIS_EXPR.prop('ref');
|
||||
}
|
||||
return injectFromViewParentInjector(diDep.token, false);
|
||||
});
|
||||
this.view.fields.push(new o.ClassField(this.instance.name, o.importType(this.meta.type),
|
||||
[o.StmtModifier.Private]));
|
||||
this.view.createMethod.resetDebugInfo(null, null);
|
||||
this.view.createMethod.addStmt(o.THIS_EXPR.prop(this.instance.name)
|
||||
.set(o.importExpr(this.meta.type).instantiate(deps))
|
||||
.toStmt());
|
||||
this._purePipeProxies.forEach((purePipeProxy) => {
|
||||
createPureProxy(
|
||||
this.instance.prop('transform').callMethod(o.BuiltinMethod.bind, [this.instance]),
|
||||
purePipeProxy.argCount, purePipeProxy.instance, this.view);
|
||||
});
|
||||
}
|
||||
|
||||
call(callingView: CompileView, args: o.Expression[]): o.Expression {
|
||||
if (this.meta.pure) {
|
||||
var purePipeProxy = new _PurePipeProxy(
|
||||
o.THIS_EXPR.prop(`${this.instance.name}_${this._purePipeProxies.length}`), args.length);
|
||||
this._purePipeProxies.push(purePipeProxy);
|
||||
return getPropertyInView(
|
||||
o.importExpr(Identifiers.castByValue)
|
||||
.callFn([purePipeProxy.instance, this.instance.prop('transform')]),
|
||||
callingView, this.view)
|
||||
.callFn(args);
|
||||
} else {
|
||||
return getPropertyInView(this.instance, callingView, this.view).callMethod('transform', args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _findPipeMeta(view: CompileView, name: string): CompilePipeMetadata {
|
||||
var pipeMeta: CompilePipeMetadata = null;
|
||||
for (var i = view.pipeMetas.length - 1; i >= 0; i--) {
|
||||
var localPipeMeta = view.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!`);
|
||||
}
|
||||
return pipeMeta;
|
||||
}
|
||||
@@ -30,14 +30,12 @@ export class CompileQuery {
|
||||
addValue(value: o.Expression, view: CompileView) {
|
||||
var currentView = view;
|
||||
var elPath: CompileElement[] = [];
|
||||
var viewPath: CompileView[] = [];
|
||||
while (isPresent(currentView) && currentView !== this.view) {
|
||||
var parentEl = currentView.declarationElement;
|
||||
elPath.unshift(parentEl);
|
||||
currentView = parentEl.view;
|
||||
viewPath.push(currentView);
|
||||
}
|
||||
var queryListForDirtyExpr = getPropertyInView(this.queryList, viewPath);
|
||||
var queryListForDirtyExpr = getPropertyInView(this.queryList, view, this.view);
|
||||
|
||||
var viewValues = this._values;
|
||||
elPath.forEach((el) => {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {ListWrapper, StringMapWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import * as o from '../output/output_ast';
|
||||
import {Identifiers, identifierToken} from '../identifiers';
|
||||
import {EventHandlerVars} from './constants';
|
||||
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
|
||||
import {NameResolver} from './expression_converter';
|
||||
import {CompileElement, CompileNode} from './compile_element';
|
||||
import {CompileMethod} from './compile_method';
|
||||
import {CompilePipe} from './compile_pipe';
|
||||
import {ViewType} from 'angular2/src/core/linker/view_type';
|
||||
import {
|
||||
CompileDirectiveMetadata,
|
||||
@@ -20,17 +19,12 @@ import {
|
||||
getViewFactoryName,
|
||||
injectFromViewParentInjector,
|
||||
createDiTokenExpression,
|
||||
getPropertyInView
|
||||
getPropertyInView,
|
||||
createPureProxy
|
||||
} from './util';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {CompileBinding} from './compile_binding';
|
||||
|
||||
import {bindPipeDestroyLifecycleCallbacks} from './lifecycle_binder';
|
||||
|
||||
export class CompilePipe {
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
export class CompileView implements NameResolver {
|
||||
public viewType: ViewType;
|
||||
public viewQueries: CompileTokenMap<CompileQuery[]>;
|
||||
@@ -60,7 +54,8 @@ export class CompileView implements NameResolver {
|
||||
public subscriptions: o.Expression[] = [];
|
||||
|
||||
public componentView: CompileView;
|
||||
public pipes = new Map<string, o.Expression>();
|
||||
public purePipes = new Map<string, CompilePipe>();
|
||||
public pipes: CompilePipe[] = [];
|
||||
public variables = new Map<string, o.Expression>();
|
||||
public className: string;
|
||||
public classType: o.Type;
|
||||
@@ -68,6 +63,7 @@ export class CompileView implements NameResolver {
|
||||
|
||||
public literalArrayCount = 0;
|
||||
public literalMapCount = 0;
|
||||
public pipeCount = 0;
|
||||
|
||||
constructor(public component: CompileDirectiveMetadata, public genConfig: CompilerConfig,
|
||||
public pipeMetas: CompilePipeMetadata[], public styles: o.Expression,
|
||||
@@ -124,39 +120,17 @@ export class CompileView implements NameResolver {
|
||||
}
|
||||
}
|
||||
|
||||
createPipe(name: string): o.Expression {
|
||||
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;
|
||||
callPipe(name: string, input: o.Expression, args: o.Expression[]): o.Expression {
|
||||
var compView = this.componentView;
|
||||
var pipe = compView.purePipes.get(name);
|
||||
if (isBlank(pipe)) {
|
||||
pipe = new CompilePipe(compView, name);
|
||||
if (pipe.pure) {
|
||||
compView.purePipes.set(name, pipe);
|
||||
}
|
||||
compView.pipes.push(pipe);
|
||||
}
|
||||
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)) {
|
||||
var deps = pipeMeta.type.diDeps.map((diDep) => {
|
||||
if (diDep.token.equalsTo(identifierToken(Identifiers.ChangeDetectorRef))) {
|
||||
return o.THIS_EXPR.prop('ref');
|
||||
}
|
||||
return injectFromViewParentInjector(diDep.token, false);
|
||||
});
|
||||
this.fields.push(
|
||||
new o.ClassField(pipeFieldName, o.importType(pipeMeta.type), [o.StmtModifier.Private]));
|
||||
this.createMethod.resetDebugInfo(null, null);
|
||||
this.createMethod.addStmt(o.THIS_EXPR.prop(pipeFieldName)
|
||||
.set(o.importExpr(pipeMeta.type).instantiate(deps))
|
||||
.toStmt());
|
||||
pipeExpr = o.THIS_EXPR.prop(pipeFieldName);
|
||||
this.pipes.set(pipeFieldName, pipeExpr);
|
||||
bindPipeDestroyLifecycleCallbacks(pipeMeta, pipeExpr, this);
|
||||
}
|
||||
return pipeExpr;
|
||||
return pipe.call(this, [input].concat(args));
|
||||
}
|
||||
|
||||
getVariable(name: string): o.Expression {
|
||||
@@ -165,29 +139,49 @@ export class CompileView implements NameResolver {
|
||||
}
|
||||
var currView: CompileView = this;
|
||||
var result = currView.variables.get(name);
|
||||
var viewPath = [];
|
||||
while (isBlank(result) && isPresent(currView.declarationElement.view)) {
|
||||
currView = currView.declarationElement.view;
|
||||
result = currView.variables.get(name);
|
||||
viewPath.push(currView);
|
||||
}
|
||||
if (isPresent(result)) {
|
||||
return getPropertyInView(result, viewPath);
|
||||
return getPropertyInView(result, this, currView);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
createLiteralArray(values: o.Expression[]): o.Expression {
|
||||
return o.THIS_EXPR.callMethod('literalArray',
|
||||
[o.literal(this.literalArrayCount++), o.literalArr(values)]);
|
||||
var proxyExpr = o.THIS_EXPR.prop(`_arr_${this.literalArrayCount++}`);
|
||||
var proxyParams: o.FnParam[] = [];
|
||||
var proxyReturnEntries: o.Expression[] = [];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var paramName = `p${i}`;
|
||||
proxyParams.push(new o.FnParam(paramName));
|
||||
proxyReturnEntries.push(o.variable(paramName));
|
||||
}
|
||||
createPureProxy(o.fn(proxyParams, [new o.ReturnStatement(o.literalArr(proxyReturnEntries))]),
|
||||
values.length, proxyExpr, this);
|
||||
return proxyExpr.callFn(values);
|
||||
}
|
||||
createLiteralMap(values: Array<Array<string | o.Expression>>): o.Expression {
|
||||
return o.THIS_EXPR.callMethod('literalMap',
|
||||
[o.literal(this.literalMapCount++), o.literalMap(values)]);
|
||||
|
||||
createLiteralMap(entries: Array<Array<string | o.Expression>>): o.Expression {
|
||||
var proxyExpr = o.THIS_EXPR.prop(`_map_${this.literalMapCount++}`);
|
||||
var proxyParams: o.FnParam[] = [];
|
||||
var proxyReturnEntries: Array<Array<string | o.Expression>> = [];
|
||||
var values: o.Expression[] = [];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var paramName = `p${i}`;
|
||||
proxyParams.push(new o.FnParam(paramName));
|
||||
proxyReturnEntries.push([entries[i][0], o.variable(paramName)]);
|
||||
values.push(<o.Expression>entries[i][1]);
|
||||
}
|
||||
createPureProxy(o.fn(proxyParams, [new o.ReturnStatement(o.literalMap(proxyReturnEntries))]),
|
||||
entries.length, proxyExpr, this);
|
||||
return proxyExpr.callFn(values);
|
||||
}
|
||||
|
||||
afterNodes() {
|
||||
this.pipes.forEach((pipe) => pipe.create());
|
||||
this.viewQueries.values().forEach(
|
||||
(queries) => queries.forEach((query) => query.afterChildren(this.updateViewQueriesMethod)));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {isBlank, isPresent, isArray, CONST_EXPR} from 'angular2/src/facade/lang'
|
||||
var IMPLICIT_RECEIVER = o.variable('#implicit');
|
||||
|
||||
export interface NameResolver {
|
||||
createPipe(name: string): o.Expression;
|
||||
callPipe(name: string, input: o.Expression, args: o.Expression[]): o.Expression;
|
||||
getVariable(name: string): o.Expression;
|
||||
createLiteralArray(values: o.Expression[]): o.Expression;
|
||||
createLiteralMap(values: Array<Array<string | o.Expression>>): o.Expression;
|
||||
@@ -132,13 +132,11 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
|
||||
ast.falseExp.visit(this, _Mode.Expression)));
|
||||
}
|
||||
visitPipe(ast: cdAst.BindingPipe, mode: _Mode): any {
|
||||
var pipeInstance = this._nameResolver.createPipe(ast.name);
|
||||
var input = ast.exp.visit(this, _Mode.Expression);
|
||||
var args = this.visitAll(ast.args, _Mode.Expression);
|
||||
var value = this._nameResolver.callPipe(ast.name, input, args);
|
||||
this.needsValueUnwrapper = true;
|
||||
return convertToStatementIfNeeded(
|
||||
mode, this._valueUnwrapper.callMethod(
|
||||
'unwrap', [pipeInstance.callMethod('transform', [input, o.literalArr(args)])]));
|
||||
return convertToStatementIfNeeded(mode, this._valueUnwrapper.callMethod('unwrap', [value]));
|
||||
}
|
||||
visitFunctionCall(ast: cdAst.FunctionCall, mode: _Mode): any {
|
||||
return convertToStatementIfNeeded(mode, ast.target.visit(this, _Mode.Expression)
|
||||
|
||||
@@ -78,10 +78,10 @@ export function bindDirectiveDestroyLifecycleCallbacks(directiveMeta: CompileDir
|
||||
}
|
||||
}
|
||||
|
||||
export function bindPipeDestroyLifecycleCallbacks(
|
||||
pipeMeta: CompilePipeMetadata, directiveInstance: o.Expression, view: CompileView) {
|
||||
export function bindPipeDestroyLifecycleCallbacks(pipeMeta: CompilePipeMetadata,
|
||||
pipeInstance: o.Expression, view: CompileView) {
|
||||
var onDestroyMethod = view.destroyMethod;
|
||||
if (pipeMeta.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1) {
|
||||
onDestroyMethod.addStmt(directiveInstance.callMethod('ngOnDestroy', []).toStmt());
|
||||
onDestroyMethod.addStmt(pipeInstance.callMethod('ngOnDestroy', []).toStmt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
import * as o from '../output/output_ast';
|
||||
import {
|
||||
@@ -7,22 +8,29 @@ import {
|
||||
CompileIdentifierMetadata
|
||||
} from '../compile_metadata';
|
||||
import {CompileView} from './compile_view';
|
||||
import {Identifiers} from '../identifiers';
|
||||
|
||||
export function getPropertyInView(property: o.Expression, viewPath: CompileView[]): o.Expression {
|
||||
if (viewPath.length === 0) {
|
||||
export function getPropertyInView(property: o.Expression, callingView: CompileView,
|
||||
definedView: CompileView): o.Expression {
|
||||
if (callingView === definedView) {
|
||||
return property;
|
||||
} else {
|
||||
var viewProp: o.Expression = o.THIS_EXPR;
|
||||
for (var i = 0; i < viewPath.length; i++) {
|
||||
viewProp = viewProp.prop('declarationAppElement').prop('parentView');
|
||||
var currView: CompileView = callingView;
|
||||
while (currView !== definedView && isPresent(currView.declarationElement.view)) {
|
||||
currView = currView.declarationElement.view;
|
||||
viewProp = viewProp.prop('parent');
|
||||
}
|
||||
if (currView !== definedView) {
|
||||
throw new BaseException(
|
||||
`Internal error: Could not calculate a property in a parent view: ${property}`);
|
||||
}
|
||||
if (property instanceof o.ReadPropExpr) {
|
||||
var lastView = viewPath[viewPath.length - 1];
|
||||
let readPropExpr: o.ReadPropExpr = property;
|
||||
// Note: Don't cast for members of the AppView base class...
|
||||
if (lastView.fields.some((field) => field.name == readPropExpr.name) ||
|
||||
lastView.getters.some((field) => field.name == readPropExpr.name)) {
|
||||
viewProp = viewProp.cast(lastView.classType);
|
||||
if (definedView.fields.some((field) => field.name == readPropExpr.name) ||
|
||||
definedView.getters.some((field) => field.name == readPropExpr.name)) {
|
||||
viewProp = viewProp.cast(definedView.classType);
|
||||
}
|
||||
}
|
||||
return o.replaceVarInExpression(o.THIS_EXPR.name, viewProp, property);
|
||||
@@ -77,3 +85,15 @@ export function createFlatArray(expressions: o.Expression[]): o.Expression {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createPureProxy(fn: o.Expression, argCount: number, pureProxyProp: o.ReadPropExpr,
|
||||
view: CompileView) {
|
||||
view.fields.push(new o.ClassField(pureProxyProp.name, null, [o.StmtModifier.Private]));
|
||||
var pureProxyId =
|
||||
argCount < Identifiers.pureProxies.length ? Identifiers.pureProxies[argCount] : null;
|
||||
if (isBlank(pureProxyId)) {
|
||||
throw new BaseException(`Unsupported number of argument for pure functions: ${argCount}`);
|
||||
}
|
||||
view.createMethod.addStmt(
|
||||
o.THIS_EXPR.prop(pureProxyProp.name).set(o.importExpr(pureProxyId).callFn([fn])).toStmt());
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import {CompileElement, CompileNode} from './compile_element';
|
||||
export function bindView(view: CompileView, parsedTemplate: TemplateAst[]): void {
|
||||
var visitor = new ViewBinderVisitor(view);
|
||||
templateVisitAll(visitor, parsedTemplate);
|
||||
view.pipes.forEach(
|
||||
(pipe) => { bindPipeDestroyLifecycleCallbacks(pipe.meta, pipe.instance, pipe.view); });
|
||||
}
|
||||
|
||||
class ViewBinderVisitor implements TemplateAstVisitor {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {isPresent, StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {isPresent, isBlank, StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper, StringMapWrapper, SetWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import * as o from '../output/output_ast';
|
||||
@@ -429,8 +429,6 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr,
|
||||
ViewConstructorVars.parentInjector,
|
||||
ViewConstructorVars.declarationEl,
|
||||
ChangeDetectionStrategyEnum.fromValue(getChangeDetectionMode(view)),
|
||||
o.literal(view.literalArrayCount),
|
||||
o.literal(view.literalMapCount),
|
||||
nodeDebugInfosVar
|
||||
])
|
||||
.toStmt()
|
||||
@@ -600,4 +598,4 @@ function getChangeDetectionMode(view: CompileView): ChangeDetectionStrategy {
|
||||
mode = ChangeDetectionStrategy.CheckAlways;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* To create a Pipe, you must implement this interface.
|
||||
*
|
||||
* Angular invokes the `transform` method with the value of a binding
|
||||
* as the first argument, and any parameters as the second argument in list form.
|
||||
*
|
||||
* ## Syntax
|
||||
*
|
||||
* `value | pipeName[:arg0[:arg1...]]`
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/f5oyIked9M2cKzvZNKHV?p=preview))
|
||||
*
|
||||
* The `RepeatPipe` below repeats the value as many times as indicated by the first argument:
|
||||
*
|
||||
* ```
|
||||
* import {Pipe, PipeTransform} from 'angular2/core';
|
||||
*
|
||||
* @Pipe({name: 'repeat'})
|
||||
* export class RepeatPipe implements PipeTransform {
|
||||
* transform(value: any, times: number) {
|
||||
* return value.repeat(times);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Invoking `{{ 'ok' | repeat:3 }}` in a template produces `okokok`.
|
||||
*
|
||||
*/
|
||||
abstract class PipeTransform {
|
||||
// Note: Dart does not support varargs,
|
||||
// so we can't type the `transform` method...
|
||||
// dynamic transform(dynamic value, List<dynamic> ...args): any;
|
||||
}
|
||||
@@ -17,11 +17,7 @@
|
||||
*
|
||||
* @Pipe({name: 'repeat'})
|
||||
* export class RepeatPipe implements PipeTransform {
|
||||
* transform(value: any, args: any[] = []) {
|
||||
* if (args.length == 0) {
|
||||
* throw new Error('repeat pipe requires one argument');
|
||||
* }
|
||||
* let times: number = args[0];
|
||||
* transform(value: any, times: number) {
|
||||
* return value.repeat(times);
|
||||
* }
|
||||
* }
|
||||
@@ -30,4 +26,4 @@
|
||||
* Invoking `{{ 'ok' | repeat:3 }}` in a template produces `okokok`.
|
||||
*
|
||||
*/
|
||||
export interface PipeTransform { transform(value: any, args: any[]): any; }
|
||||
export interface PipeTransform { transform(value: any, ...args: any[]): any; }
|
||||
|
||||
@@ -70,9 +70,6 @@ export abstract class AppView<T> {
|
||||
renderParent: AppView<any>;
|
||||
viewContainerElement: AppElement = null;
|
||||
|
||||
private _literalArrayCache: any[][];
|
||||
private _literalMapCache: Array<{[key: string]: any}>;
|
||||
|
||||
// The names of the below fields must be kept in sync with codegen_name_util.ts or
|
||||
// change detection will fail.
|
||||
cdState: ChangeDetectorState = ChangeDetectorState.NeverChecked;
|
||||
@@ -96,16 +93,14 @@ export abstract class AppView<T> {
|
||||
constructor(public clazz: any, public componentType: RenderComponentType, public type: ViewType,
|
||||
public locals: {[key: string]: any}, public viewUtils: ViewUtils,
|
||||
public parentInjector: Injector, public declarationAppElement: AppElement,
|
||||
public cdMode: ChangeDetectionStrategy, literalArrayCacheSize: number,
|
||||
literalMapCacheSize: number, public staticNodeDebugInfos: StaticNodeDebugInfo[]) {
|
||||
public cdMode: ChangeDetectionStrategy,
|
||||
public staticNodeDebugInfos: StaticNodeDebugInfo[]) {
|
||||
this.ref = new ViewRef_(this);
|
||||
if (type === ViewType.COMPONENT || type === ViewType.HOST) {
|
||||
this.renderer = viewUtils.renderComponent(componentType);
|
||||
} else {
|
||||
this.renderer = declarationAppElement.parentView.renderer;
|
||||
}
|
||||
this._literalArrayCache = ListWrapper.createFixedSize(literalArrayCacheSize);
|
||||
this._literalMapCache = ListWrapper.createFixedSize(literalMapCacheSize);
|
||||
}
|
||||
|
||||
create(givenProjectableNodes: Array<any | any[]>, rootSelectorOrNode: string | any): AppElement {
|
||||
@@ -269,6 +264,10 @@ export abstract class AppView<T> {
|
||||
|
||||
get changeDetectorRef(): ChangeDetectorRef { return this.ref; }
|
||||
|
||||
get parent(): AppView<any> {
|
||||
return isPresent(this.declarationAppElement) ? this.declarationAppElement.parentView : null;
|
||||
}
|
||||
|
||||
get flatRootNodes(): any[] { return flattenNestedViewRenderNodes(this.rootNodesOrAppElements); }
|
||||
|
||||
get lastRootNode(): any {
|
||||
@@ -360,28 +359,6 @@ export abstract class AppView<T> {
|
||||
this.viewContainerElement = null;
|
||||
}
|
||||
|
||||
literalArray(id: number, value: any[]): any[] {
|
||||
var prevValue = this._literalArrayCache[id];
|
||||
if (isBlank(value)) {
|
||||
return value;
|
||||
}
|
||||
if (isBlank(prevValue) || !arrayLooseIdentical(prevValue, value)) {
|
||||
prevValue = this._literalArrayCache[id] = value;
|
||||
}
|
||||
return prevValue;
|
||||
}
|
||||
|
||||
literalMap(id: number, value: {[key: string]: any}): {[key: string]: any} {
|
||||
var prevValue = this._literalMapCache[id];
|
||||
if (isBlank(value)) {
|
||||
return value;
|
||||
}
|
||||
if (isBlank(prevValue) || !mapLooseIdentical(prevValue, value)) {
|
||||
prevValue = this._literalMapCache[id] = value;
|
||||
}
|
||||
return prevValue;
|
||||
}
|
||||
|
||||
markAsCheckOnce(): void { this.cdMode = ChangeDetectionStrategy.CheckOnce; }
|
||||
|
||||
markPathToRootAsCheckOnce(): void {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {AppElement} from './element';
|
||||
import {ExpressionChangedAfterItHasBeenCheckedException} from './exceptions';
|
||||
import {devModeEqual} from 'angular2/src/core/change_detection/change_detection';
|
||||
import {devModeEqual, uninitialized} from 'angular2/src/core/change_detection/change_detection';
|
||||
import {Inject, Injectable} from 'angular2/src/core/di';
|
||||
import {RootRenderer, RenderComponentType, Renderer} from 'angular2/src/core/render/api';
|
||||
import {APP_ID} from 'angular2/src/core/application_tokens';
|
||||
@@ -158,3 +158,209 @@ export function mapLooseIdentical<V>(m1: {[key: string]: V}, m2: {[key: string]:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function castByValue<T>(input: any, value: T): T {
|
||||
return <T>input;
|
||||
}
|
||||
|
||||
export function pureProxy1<P0, R>(fn: (p0: P0) => R): (p0: P0) => R {
|
||||
var result: R;
|
||||
var v0;
|
||||
v0 = uninitialized;
|
||||
return (p0) => {
|
||||
if (!looseIdentical(v0, p0)) {
|
||||
v0 = p0;
|
||||
result = fn(p0);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy2<P0, P1, R>(fn: (p0: P0, p1: P1) => R): (p0: P0, p1: P1) => R {
|
||||
var result: R;
|
||||
var v0, v1;
|
||||
v0 = v1 = uninitialized;
|
||||
return (p0, p1) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
result = fn(p0, p1);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy3<P0, P1, P2, R>(fn: (p0: P0, p1: P1, p2: P2) => R): (p0: P0, p1: P1,
|
||||
p2: P2) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2;
|
||||
v0 = v1 = v2 = uninitialized;
|
||||
return (p0, p1, p2) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
result = fn(p0, p1, p2);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy4<P0, P1, P2, P3, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3) => R): (
|
||||
p0: P0, p1: P1, p2: P2, p3: P3) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3;
|
||||
v0 = v1 = v2 = v3 = uninitialized;
|
||||
return (p0, p1, p2, p3) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
result = fn(p0, p1, p2, p3);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy5<P0, P1, P2, P3, P4, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) =>
|
||||
R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4;
|
||||
v0 = v1 = v2 = v3 = v4 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
result = fn(p0, p1, p2, p3, p4);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function pureProxy6<P0, P1, P2, P3, P4, P5, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => R): (p0: P0, p1: P1, p2: P2, p3: P3,
|
||||
p4: P4, p5: P5) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4, v5;
|
||||
v0 = v1 = v2 = v3 = v4 = v5 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4, p5) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
v5 = p5;
|
||||
result = fn(p0, p1, p2, p3, p4, p5);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy7<P0, P1, P2, P3, P4, P5, P6, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) =>
|
||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4, v5, v6;
|
||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4, p5, p6) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
||||
!looseIdentical(v6, p6)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
v5 = p5;
|
||||
v6 = p6;
|
||||
result = fn(p0, p1, p2, p3, p4, p5, p6);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy8<P0, P1, P2, P3, P4, P5, P6, P7, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) =>
|
||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4, v5, v6, v7;
|
||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4, p5, p6, p7) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
v5 = p5;
|
||||
v6 = p6;
|
||||
v7 = p7;
|
||||
result = fn(p0, p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy9<P0, P1, P2, P3, P4, P5, P6, P7, P8, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) =>
|
||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4, v5, v6, v7, v8;
|
||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4, p5, p6, p7, p8) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7) || !looseIdentical(v8, p8)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
v5 = p5;
|
||||
v6 = p6;
|
||||
v7 = p7;
|
||||
v8 = p8;
|
||||
result = fn(p0, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function pureProxy10<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, R>(
|
||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) =>
|
||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) => R {
|
||||
var result: R;
|
||||
var v0, v1, v2, v3, v4, v5, v6, v7, v8, v9;
|
||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = uninitialized;
|
||||
return (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) => {
|
||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7) || !looseIdentical(v8, p8) ||
|
||||
!looseIdentical(v9, p9)) {
|
||||
v0 = p0;
|
||||
v1 = p1;
|
||||
v2 = p2;
|
||||
v3 = p3;
|
||||
v4 = p4;
|
||||
v5 = p5;
|
||||
v6 = p6;
|
||||
v7 = p7;
|
||||
v8 = p8;
|
||||
v9 = p9;
|
||||
result = fn(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user