Skip to content

Commit

Permalink
feat(composition): enable composition transaction use
Browse files Browse the repository at this point in the history
  • Loading branch information
EisenbergEffect committed Feb 16, 2016
1 parent 2f2e156 commit b8e51df
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 31 deletions.
63 changes: 42 additions & 21 deletions src/composition-engine.js
Expand Up @@ -2,6 +2,7 @@ import {ViewLocator} from './view-locator';
import {ViewEngine} from './view-engine';
import {HtmlBehaviorResource} from './html-behavior';
import {BehaviorInstruction, ViewCompileInstruction} from './instructions';
import {CompositionTransaction} from './composition-transaction';
import {DOM} from 'aurelia-pal';
import {Container, inject} from 'aurelia-dependency-injection';
import {metadata} from 'aurelia-metadata';
Expand Down Expand Up @@ -83,25 +84,31 @@ export class CompositionEngine {
}

_createControllerAndSwap(context) {
let removeResponse = context.viewSlot.removeAll(true);
let afterRemove = () => {
return this.createController(context).then(controller => {
function swap(controller) {
return Promise.resolve(context.viewSlot.removeAll(true)).then(() => {
if (context.currentController) {
context.currentController.unbind();
}

controller.automate(context.overrideContext, context.owningView);
context.viewSlot.add(controller.view);

if (context.compositionTransactionNotifier) {
context.compositionTransactionNotifier.done();
}

return controller;
});
};

if (removeResponse instanceof Promise) {
return removeResponse.then(afterRemove);
}

return afterRemove();

return this.createController(context).then(controller => {
controller.automate(context.overrideContext, context.owningView);

if (context.compositionTransactionOwnershipToken) {
return context.compositionTransactionOwnershipToken.waitForCompositionComplete().then(() => swap(controller));
} else {
return swap(controller);
}
});
}

/**
Expand Down Expand Up @@ -173,6 +180,15 @@ export class CompositionEngine {
compose(context: CompositionContext): Promise<View | Controller> {
context.childContainer = context.childContainer || context.container.createChild();
context.view = this.viewLocator.getViewStrategy(context.view);

let transaction = context.childContainer.get(CompositionTransaction);
let compositionTransactionOwnershipToken = transaction.tryCapture();

if (compositionTransactionOwnershipToken) {
context.compositionTransactionOwnershipToken = compositionTransactionOwnershipToken;
} else {
context.compositionTransactionNotifier = transaction.enlist();
}

if (context.viewModel) {
return this._createControllerAndSwap(context);
Expand All @@ -182,21 +198,26 @@ export class CompositionEngine {
}

return context.view.loadViewFactory(this.viewEngine, new ViewCompileInstruction()).then(viewFactory => {
let removeResponse = context.viewSlot.removeAll(true);

if (removeResponse instanceof Promise) {
return removeResponse.then(() => {
let result = viewFactory.create(context.childContainer);
result.bind(context.bindingContext, context.overrideContext);
let result = viewFactory.create(context.childContainer);
result.bind(context.bindingContext, context.overrideContext);

let work = () => {
return Promise.resolve(context.viewSlot.removeAll(true)).then(() => {
context.viewSlot.add(result);

if (context.compositionTransactionNotifier) {
context.compositionTransactionNotifier.done();
}

return result;
});
};

if (context.compositionTransactionOwnershipToken) {
return context.compositionTransactionOwnershipToken.waitForCompositionComplete().then(work);
} else {
return work();
}

let result = viewFactory.create(context.childContainer);
result.bind(context.bindingContext, context.overrideContext);
context.viewSlot.add(result);
return result;
});
} else if (context.viewSlot) {
context.viewSlot.removeAll();
Expand Down
27 changes: 17 additions & 10 deletions src/composition-transaction.js
@@ -1,3 +1,5 @@
import {TaskQueue} from 'aurelia-task-queue';
import {inject} from 'aurelia-dependency-injection';

interface CompositionTransactionOwnershipToken {
compositionInProcess: boolean;
Expand All @@ -11,11 +13,13 @@ interface CompositionTransactionNotifier {
/**
* Enables an initiator of a view composition to track any internal async rendering processes for completion.
*/
@inject(TaskQueue)
export class CompositionTransaction {
/**
* Creates an instance of CompositionTransaction.
*/
constructor() {
constructor(taskQueue: TaskQueue) {
this._taskQueue = taskQueue;
this._ownershipToken = null;
this._compositionCount = 0;
}
Expand Down Expand Up @@ -61,15 +65,17 @@ export class CompositionTransaction {
}

_tryCompleteTransaction() {
if (this._compositionCount <= 0) {
this._compositionCount = 0;

if (this._ownershipToken !== null) {
let capture = this._ownershipToken;
this._ownershipToken = null;
capture._resolve();
//this._taskQueue.queueMicroTask(() => {
if (this._compositionCount <= 0) {
this._compositionCount = 0;

if (this._ownershipToken !== null) {
let capture = this._ownershipToken;
this._ownershipToken = null;
capture._resolve();
}
}
}
//});
}

_createOwnershipToken(): CompositionTransactionOwnershipToken {
Expand All @@ -78,7 +84,8 @@ export class CompositionTransaction {
token._resolve = resolve;
});

token.waitForCompositionComplete = function() {
token.waitForCompositionComplete = () => {
this._tryCompleteTransaction();
return promise;
};

Expand Down
5 changes: 5 additions & 0 deletions src/view-factory.js
Expand Up @@ -6,6 +6,7 @@ import {ViewResources} from './view-resources';
import {BehaviorInstruction, TargetInstruction} from './instructions';
import {DOM} from 'aurelia-pal';
import {ElementEvents} from './element-events';
import {CompositionTransaction} from './composition-transaction';

@resolver
class ProviderResolver {
Expand Down Expand Up @@ -51,6 +52,10 @@ function elementContainerGet(key) {
if (key === ElementEvents) {
return this.elementEvents || (this.elementEvents = new ElementEvents(this.element));
}

if (key === CompositionTransaction) {
return this.compositionTransaction || (this.compositionTransaction = this.parent.get(key));
}

if (key === ViewResources) {
return this.viewResources;
Expand Down

0 comments on commit b8e51df

Please sign in to comment.