fix(compiler): fix where pipes live
Impure pipes need to live on the view
that used them and need a new instance for
each call site.
Impure pipes need to live on the component view, cached across all child views,
and need a new pure proxy for each for
each call site that lives on the view
of the call site.
Fixes #8408
This bug was introduced not long ago by 152a117d5c
This commit is contained in:
@ -7,17 +7,35 @@ import {Identifiers, identifierToken} from '../identifiers';
|
||||
import {injectFromViewParentInjector, createPureProxy, getPropertyInView} from './util';
|
||||
|
||||
class _PurePipeProxy {
|
||||
constructor(public instance: o.ReadPropExpr, public argCount: number) {}
|
||||
constructor(public view: CompileView, public instance: o.ReadPropExpr, public argCount: number) {}
|
||||
}
|
||||
|
||||
export class CompilePipe {
|
||||
meta: CompilePipeMetadata;
|
||||
static call(view: CompileView, name: string, args: o.Expression[]): o.Expression {
|
||||
var compView = view.componentView;
|
||||
var meta = _findPipeMeta(compView, name);
|
||||
var pipe: CompilePipe;
|
||||
if (meta.pure) {
|
||||
// pure pipes live on the component view
|
||||
pipe = compView.purePipes.get(name);
|
||||
if (isBlank(pipe)) {
|
||||
pipe = new CompilePipe(compView, meta);
|
||||
compView.purePipes.set(name, pipe);
|
||||
compView.pipes.push(pipe);
|
||||
}
|
||||
} else {
|
||||
// Non pure pipes live on the view that called it
|
||||
pipe = new CompilePipe(view, meta);
|
||||
view.pipes.push(pipe);
|
||||
}
|
||||
return pipe._call(view, args);
|
||||
}
|
||||
|
||||
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++}`);
|
||||
constructor(public view: CompileView, public meta: CompilePipeMetadata) {
|
||||
this.instance = o.THIS_EXPR.prop(`_pipe_${meta.name}_${view.pipeCount++}`);
|
||||
}
|
||||
|
||||
get pure(): boolean { return this.meta.pure; }
|
||||
@ -35,21 +53,26 @@ export class CompilePipe {
|
||||
.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);
|
||||
var pipeInstanceSeenFromPureProxy =
|
||||
getPropertyInView(this.instance, purePipeProxy.view, this.view);
|
||||
createPureProxy(pipeInstanceSeenFromPureProxy.prop('transform')
|
||||
.callMethod(o.BuiltinMethod.bind, [pipeInstanceSeenFromPureProxy]),
|
||||
purePipeProxy.argCount, purePipeProxy.instance, purePipeProxy.view);
|
||||
});
|
||||
}
|
||||
|
||||
call(callingView: CompileView, args: o.Expression[]): o.Expression {
|
||||
private _call(callingView: CompileView, args: o.Expression[]): o.Expression {
|
||||
if (this.meta.pure) {
|
||||
// PurePipeProxies live on the view that called them.
|
||||
var purePipeProxy = new _PurePipeProxy(
|
||||
o.THIS_EXPR.prop(`${this.instance.name}_${this._purePipeProxies.length}`), args.length);
|
||||
callingView, 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)
|
||||
return o.importExpr(Identifiers.castByValue)
|
||||
.callFn([
|
||||
purePipeProxy.instance,
|
||||
getPropertyInView(this.instance.prop('transform'), callingView, this.view)
|
||||
])
|
||||
.callFn(args);
|
||||
} else {
|
||||
return getPropertyInView(this.instance, callingView, this.view).callMethod('transform', args);
|
||||
@ -57,7 +80,6 @@ export class CompilePipe {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _findPipeMeta(view: CompileView, name: string): CompilePipeMetadata {
|
||||
var pipeMeta: CompilePipeMetadata = null;
|
||||
for (var i = view.pipeMetas.length - 1; i >= 0; i--) {
|
||||
|
@ -127,16 +127,7 @@ export class CompileView implements NameResolver {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return pipe.call(this, [input].concat(args));
|
||||
return CompilePipe.call(this, name, [input].concat(args));
|
||||
}
|
||||
|
||||
getLocal(name: string): o.Expression {
|
||||
|
Reference in New Issue
Block a user