Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
public $unbind(flags: LifecycleFlags): void {
if (Tracer.enabled) { Tracer.enter('Call', '$unbind', slice.call(arguments)); }
if (!(this.$state & State.isBound)) {
if (Tracer.enabled) { Tracer.leave(); }
return;
}
// add isUnbinding flag
this.$state |= State.isUnbinding;
if (hasUnbind(this.sourceExpression)) {
this.sourceExpression.unbind(flags, this.$scope!, this);
}
this.$scope = void 0;
this.targetObserver.setValue(null, flags);
// remove isBound and isUnbinding flags
this.$state &= ~(State.isBound | State.isUnbinding);
public processBindQueue(flags: LifecycleFlags): void {
if (Tracer.enabled) { Tracer.enter('Lifecycle', 'processBindQueue', slice.call(arguments)); }
// flush before processing bound callbacks, but only if this is the initial bind;
// no DOM is attached yet so we can safely let everything propagate
if (flags & LifecycleFlags.fromStartTask) {
this.processFlushQueue(flags | LifecycleFlags.fromSyncFlush);
}
// bound callbacks may lead to additional bind operations, so keep looping until
// the bound head is back to `this` (though this will typically happen in the first iteration)
while (this.boundCount > 0) {
this.boundCount = 0;
let current = this.boundHead.$nextBound;
let next: ILifecycleHooks;
this.boundHead = this.boundTail = this;
do {
current.bound(flags);
next = current.$nextBound;
current.$nextBound = null;
private bindManifest(parentManifest: ElementSymbol, node: IHTMLTemplateElement | IHTMLElement): void {
if (Tracer.enabled) { Tracer.enter('TemplateBinder.bindManifest', slice.call(arguments)); }
switch (node.nodeName) {
case 'LET':
// let cannot have children and has some different processing rules, so return early
this.bindLetElement(parentManifest, node);
if (Tracer.enabled) { Tracer.leave(); }
return;
case 'SLOT':
// slot requires no compilation
this.surrogate.hasSlots = true;
if (Tracer.enabled) { Tracer.leave(); }
return;
}
// nodes are processed bottom-up so we need to store the manifests before traversing down and
// restore them again afterwards
public $unbind(flags: LifecycleFlags): void {
if (Tracer.enabled) { Tracer.enter('Call', '$unbind', slice.call(arguments)); }
if (!(this.$state & State.isBound)) {
if (Tracer.enabled) { Tracer.leave(); }
return;
}
// add isUnbinding flag
this.$state |= State.isUnbinding;
if (hasUnbind(this.sourceExpression)) {
this.sourceExpression.unbind(flags, this.$scope, this);
}
this.$scope = null;
this.targetObserver.setValue(null, flags);
// remove isBound and isUnbinding flags
this.$state &= ~(State.isBound | State.isUnbinding);
public processAttachQueue(flags: LifecycleFlags): void {
if (Tracer.enabled) { Tracer.enter('Lifecycle', 'processAttachQueue', slice.call(arguments)); }
// flush and patch before starting the attach lifecycle to ensure batched collection changes are propagated to repeaters
// and the DOM is updated
this.processFlushQueue(flags | LifecycleFlags.fromSyncFlush);
// TODO: prevent duplicate updates coming from the patch queue (or perhaps it's just not needed in its entirety?)
//this.processPatchQueue(flags | LifecycleFlags.fromSyncFlush);
if (this.mountCount > 0) {
this.mountCount = 0;
let currentMount = this.mountHead.$nextMount;
this.mountHead = this.mountTail = this as unknown as IMountableComponent;
let nextMount: typeof currentMount;
do {
currentMount.$mount(flags);
nextMount = currentMount.$nextMount;
currentMount.$nextMount = null;
private bindAttributes(node: IHTMLTemplateElement | IHTMLElement, parentManifest: ElementSymbol): void {
if (Tracer.enabled) { Tracer.enter('TemplateBinder.bindAttributes', slice.call(arguments)); }
const { parentManifestRoot, manifestRoot, manifest } = this;
// This is the top-level symbol for the current depth.
// If there are no template controllers or replace-parts, it is always the manifest itself.
// If there are template controllers, then this will be the outer-most TemplateControllerSymbol.
let manifestProxy = manifest as ParentNodeSymbol;
const replacePart = this.declareReplacePart(node);
let previousController: TemplateControllerSymbol;
let currentController: TemplateControllerSymbol;
const attributes = node.attributes;
let i = 0;
while (i < attributes.length) {
const attr = attributes[i];
public getValue(): unknown {
if (Tracer.enabled) { Tracer.enter('GetterObserver', 'getValue', slice.call(arguments)); }
if (this.subscriberCount === 0 || this.isCollecting) {
this.currentValue = Reflect.apply(this.descriptor.get, this.proxy, PLATFORM.emptyArray);
} else {
this.currentValue = Reflect.apply(this.descriptor.get, this.obj, PLATFORM.emptyArray);
}
if (Tracer.enabled) { Tracer.leave(); }
return this.currentValue;
}
public getValueAndCollectDependencies(requireCollect: boolean): unknown {
if (Tracer.enabled) { Tracer.enter('GetterObserver', 'getValueAndCollectDependencies', slice.call(arguments)); }
const dynamicDependencies = !this.overrides.static || requireCollect;
if (dynamicDependencies) {
this.unsubscribeAllDependencies();
this.isCollecting = true;
}
this.currentValue = this.getValue();
if (dynamicDependencies) {
this.propertyDeps.forEach(x => { x.subscribe(this); });
this.collectionDeps.forEach(x => { x.subscribeToCollection(this); });
this.isCollecting = false;
}
if (Tracer.enabled) { Tracer.leave(); }
private swap(view: IView, flags: LifecycleFlags): void {
if (Tracer.enabled) { Tracer.enter('CompositionCoordinator', 'swap', slice.call(arguments)); }
if (this.currentView === view) {
if (Tracer.enabled) { Tracer.leave(); }
return;
}
const $lifecycle = this.$lifecycle;
const swapTask = new AggregateLifecycleTask();
let lifecycleTask: ILifecycleTask;
let currentView = this.currentView;
if (currentView === null) {
lifecycleTask = LifecycleTask.done;
} else {
$lifecycle.enqueueUnbindAfterDetach(currentView);
$lifecycle.beginDetach();
currentView.$detach(flags);
function createElementForTag(dom: IDOM, tagName: string, props?: Record, children?: ArrayLike): RenderPlan {
if (Tracer.enabled) { Tracer.enter('createElement', 'createElementForTag', slice.call(arguments)); }
const instructions: HTMLTargetedInstruction[] = [];
const allInstructions: HTMLTargetedInstruction[][] = [];
const dependencies: IRegistry[] = [];
const element = dom.createElement(tagName);
let hasInstructions = false;
if (props) {
Object.keys(props)
.forEach(to => {
const value = props[to];
if (isHTMLTargetedInstruction(value)) {
hasInstructions = true;
instructions.push(value);
} else {
dom.setAttribute(element, to, value);