Permalink
Browse files

fix(Let): respect DOM order

  • Loading branch information...
bigopon authored and EisenbergEffect committed Sep 24, 2018
1 parent b898ef7 commit dd4ff6755be822aff99170b8a06a2bc42d178e6a
Showing with 89 additions and 63 deletions.
  1. +2 −2 src/binding-language.js
  2. +56 −54 src/instructions.js
  3. +12 −7 src/view-compiler.js
  4. +19 −0 src/view-factory.js
@@ -2,11 +2,11 @@ function mi(name) {
throw new Error(`BindingLanguage must implement ${name}().`);
}
export interface LetExpression {
interface LetExpression {
createBinding(): LetBinding
}
export interface LetBinding {
interface LetBinding {
updateSource(): any;
call(context): any;
bind(source?: any): any;
@@ -161,55 +161,59 @@ export class BehaviorInstruction {
instruction.inheritBindingContext = true;
return instruction;
}
/**
* Creates an instance of BehaviorInstruction.
*/
constructor() {
this.initiatedByBehavior = false;
this.enhance = false;
this.partReplacements = null;
this.viewFactory = null;
this.originalAttrName = null;
this.skipContentProcessing = false;
this.contentFactory = null;
this.viewModel = null;
this.anchorIsContainer = false;
this.host = null;
this.attributes = null;
this.type = null;
this.attrName = null;
this.inheritBindingContext = false;
}
}
const biProto = BehaviorInstruction.prototype;
biProto.initiatedByBehavior = false;
biProto.enhance = false;
biProto.partReplacements = null;
biProto.viewFactory = null;
biProto.originalAttrName = null;
biProto.skipContentProcessing = false;
biProto.contentFactory = null;
biProto.viewModel = null;
biProto.anchorIsContainer = false;
biProto.host = null;
biProto.attributes = null;
biProto.type = null;
biProto.attrName = null;
biProto.inheritBindingContext = false;
BehaviorInstruction.normal = new BehaviorInstruction();
/**
* Provides all the instructions for how a target element should be enhanced inside of a view.
*/
export class TargetInstruction {
injectorId:number;
parentInjectorId:number;
injectorId: number;
parentInjectorId: number;
shadowSlot: boolean;
slotName: string;
slotFallbackFactory: any;
shadowSlot:boolean;
slotName:string;
slotFallbackFactory:any;
/**
* Indicates if this instruction is targeting a text node
*/
contentExpression: any;
contentExpression:any;
/**
* Indicates if this instruction is a let element instruction
*/
letElement: boolean;
expressions:Array<Object>;
behaviorInstructions:Array<BehaviorInstruction>;
providers:Array<Function>;
expressions: Array<Object>;
behaviorInstructions: Array<BehaviorInstruction>;
providers: Array<Function>;
viewFactory:ViewFactory;
viewFactory: ViewFactory;
anchorIsContainer:boolean;
elementInstruction:BehaviorInstruction;
lifting:boolean;
anchorIsContainer: boolean;
elementInstruction: BehaviorInstruction;
lifting: boolean;
values:Object;
values: Object;
/**
* An empty array used to represent a target with no binding expressions.
@@ -294,30 +298,28 @@ export class TargetInstruction {
instruction.values = values;
return instruction;
}
}
/**
* Creates an instance of TargetInstruction.
*/
constructor() {
this.injectorId = null;
this.parentInjectorId = null;
const tiProto = TargetInstruction.prototype;
this.shadowSlot = false;
this.slotName = null;
this.slotFallbackFactory = null;
tiProto.injectorId = null;
tiProto.parentInjectorId = null;
this.contentExpression = null;
tiProto.shadowSlot = false;
tiProto.slotName = null;
tiProto.slotFallbackFactory = null;
this.expressions = null;
this.behaviorInstructions = null;
this.providers = null;
tiProto.contentExpression = null;
tiProto.letElement = false;
this.viewFactory = null;
tiProto.expressions = null;
tiProto.expressions = null;
tiProto.providers = null;
this.anchorIsContainer = false;
this.elementInstruction = null;
this.lifting = false;
tiProto.viewFactory = null;
this.values = null;
}
}
tiProto.anchorIsContainer = false;
tiProto.elementInstruction = null;
tiProto.lifting = false;
tiProto.values = null;
@@ -325,14 +325,19 @@ export class ViewCompiler {
}
return node.nextSibling;
} else if (tagName === 'let') {
bindingLanguage.createLetExpressions(
resources,
node,
instructions.letExpressions
auTargetID = makeIntoInstructionTarget(node);
instructions[auTargetID] = TargetInstruction.normal(
undefined,
undefined,
providers,
behaviorInstructions,
bindingLanguage.createLetExpressions(
resources,
node,
instructions.letExpressions
)
);
nextSib = node.nextSibling;
DOM.removeNode(node);
return nextSib;
return node.nextSibling;
} else if (tagName === 'template') {
if (!('content' in node)) {
throw new Error('You cannot place a template element within ' + node.namespaceURI + ' namespace');
@@ -126,6 +126,17 @@ function makeElementIntoAnchor(element, elementInstruction) {
return anchor;
}
/**
* @param {Container[]} containers
* @param {Element} element
* @param {TargetInstruction} instruction
* @param {Controller[]} controllers
* @param {Binding[]} bindings
* @param {ViewNode[]} children
* @param {Record<string, ShadowSlot>} shadowSlots
* @param {Record<string, ViewFactory>} partReplacements
* @param {ViewResources} resources
*/
function applyInstructions(containers, element, instruction, controllers, bindings, children, shadowSlots, partReplacements, resources) {
let behaviorInstructions = instruction.behaviorInstructions;
let expressions = instruction.expressions;
@@ -158,6 +169,14 @@ function applyInstructions(containers, element, instruction, controllers, bindin
return;
}
if (instruction.letExpressions) {
for (i = 0, ii = expressions.length; i < ii; ++i) {
bindings.push(expressions[i].createBinding());
}
element.parentNode.removeChild(element);
return;
}
if (behaviorInstructions.length) {
if (!instruction.anchorIsContainer) {
element = makeElementIntoAnchor(element, instruction.elementInstruction);

0 comments on commit dd4ff67

Please sign in to comment.