From 5fdb3a4588ecd720be38a97b7b6e852a5f37fb14 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Wed, 11 Nov 2015 22:45:07 -0500 Subject: [PATCH] chore(all): prepare release 0.17.1 --- bower.json | 2 +- dist/amd/compose.js | 16 +++++++++++++--- dist/amd/repeat.js | 40 ++++++++++++++++++++++++++++++---------- dist/commonjs/compose.js | 16 +++++++++++++--- dist/commonjs/repeat.js | 40 ++++++++++++++++++++++++++++++---------- dist/es6/compose.js | 17 ++++++++++++++--- dist/es6/repeat.js | 39 +++++++++++++++++++++++++++++---------- dist/system/compose.js | 16 +++++++++++++--- dist/system/repeat.js | 40 ++++++++++++++++++++++++++++++---------- doc/CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 11 files changed, 185 insertions(+), 54 deletions(-) diff --git a/bower.json b/bower.json index a83e7a7..c3f3aca 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "aurelia-templating-resources", - "version": "0.17.0", + "version": "0.17.1", "description": "A standard set of behaviors, converters and other resources for use with the Aurelia templating library.", "keywords": [ "aurelia", diff --git a/dist/amd/compose.js b/dist/amd/compose.js index a8e4110..48ad60f 100644 --- a/dist/amd/compose.js +++ b/dist/amd/compose.js @@ -48,8 +48,9 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-task-queue', 'aureli this.currentViewModel = null; } - Compose.prototype.bind = function bind(bindingContext) { - this.$parent = bindingContext; + Compose.prototype.bind = function bind(bindingContext, overrideContext) { + this.bindingContext = bindingContext; + this.overrideContext = overrideContext; processInstruction(this, createInstruction(this, { view: this.view, viewModel: this.viewModel, @@ -57,6 +58,14 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-task-queue', 'aureli })); }; + Compose.prototype.unbind = function unbind(bindingContext, overrideContext) { + this.bindingContext = null; + this.overrideContext = null; + var returnToCache = true; + var skipAnimation = true; + this.viewSlot.removeAll(returnToCache, skipAnimation); + }; + Compose.prototype.modelChanged = function modelChanged(newValue, oldValue) { var _this = this; @@ -130,7 +139,8 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-task-queue', 'aureli function createInstruction(composer, instruction) { return Object.assign(instruction, { - bindingContext: composer.$parent, + bindingContext: composer.bindingContext, + overrideContext: composer.overrideContext, container: composer.container, viewSlot: composer.viewSlot, viewResources: composer.viewResources, diff --git a/dist/amd/repeat.js b/dist/amd/repeat.js index b059476..c785b6a 100644 --- a/dist/amd/repeat.js +++ b/dist/amd/repeat.js @@ -54,6 +54,7 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-t this.key = 'key'; this.value = 'value'; this.collectionStrategyLocator = collectionStrategyLocator; + this.ignoreMutation = false; } Repeat.prototype.call = function call(context, changes) { @@ -62,21 +63,20 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-t Repeat.prototype.bind = function bind(bindingContext, overrideContext) { var items = this.items; + this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); + this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; if (items === undefined || items === null) { return; } - - this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); - this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; - this.collectionStrategy = this.collectionStrategyLocator.getStrategy(this.items); - this.collectionStrategy.initialize(this, bindingContext, overrideContext); this.processItems(); }; Repeat.prototype.unbind = function unbind() { this.sourceExpression = null; this.scope = null; - this.collectionStrategy.dispose(); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); + } this.items = null; this.collectionStrategy = null; this.viewSlot.removeAll(true); @@ -99,17 +99,27 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-t var _this = this; var items = this.items; - var rmPromise = undefined; - if (this.collectionObserver) { - this.unsubscribeCollection(); - rmPromise = this.viewSlot.removeAll(true); + this.unsubscribeCollection(); + var rmPromise = this.viewSlot.removeAll(true); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); } if (!items && items !== 0) { return; } + var bindingContext = undefined; + var overrideContext = undefined; + if (this.scope) { + bindingContext = this.scope.bindingContext; + overrideContext = this.scope.overrideContext; + } + + this.collectionStrategy = this.collectionStrategyLocator.getStrategy(items); + this.collectionStrategy.initialize(this, bindingContext, overrideContext); + if (rmPromise instanceof Promise) { rmPromise.then(function () { _this.processItemsByStrategy(); @@ -162,7 +172,17 @@ define(['exports', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-t }; Repeat.prototype.handleInnerCollectionChanges = function handleInnerCollectionChanges(collection, changes) { + var _this2 = this; + + if (this.ignoreMutation) { + return; + } + this.ignoreMutation = true; var newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); + this.observerLocator.taskQueue.queueMicroTask(function () { + return _this2.ignoreMutation = false; + }); + if (newItems === this.items) { return; } diff --git a/dist/commonjs/compose.js b/dist/commonjs/compose.js index 1c6a5b0..b47d529 100644 --- a/dist/commonjs/compose.js +++ b/dist/commonjs/compose.js @@ -55,8 +55,9 @@ var Compose = (function () { this.currentViewModel = null; } - Compose.prototype.bind = function bind(bindingContext) { - this.$parent = bindingContext; + Compose.prototype.bind = function bind(bindingContext, overrideContext) { + this.bindingContext = bindingContext; + this.overrideContext = overrideContext; processInstruction(this, createInstruction(this, { view: this.view, viewModel: this.viewModel, @@ -64,6 +65,14 @@ var Compose = (function () { })); }; + Compose.prototype.unbind = function unbind(bindingContext, overrideContext) { + this.bindingContext = null; + this.overrideContext = null; + var returnToCache = true; + var skipAnimation = true; + this.viewSlot.removeAll(returnToCache, skipAnimation); + }; + Compose.prototype.modelChanged = function modelChanged(newValue, oldValue) { var _this = this; @@ -137,7 +146,8 @@ exports.Compose = Compose; function createInstruction(composer, instruction) { return Object.assign(instruction, { - bindingContext: composer.$parent, + bindingContext: composer.bindingContext, + overrideContext: composer.overrideContext, container: composer.container, viewSlot: composer.viewSlot, viewResources: composer.viewResources, diff --git a/dist/commonjs/repeat.js b/dist/commonjs/repeat.js index 76c0d9b..34e52c1 100644 --- a/dist/commonjs/repeat.js +++ b/dist/commonjs/repeat.js @@ -61,6 +61,7 @@ var Repeat = (function () { this.key = 'key'; this.value = 'value'; this.collectionStrategyLocator = collectionStrategyLocator; + this.ignoreMutation = false; } Repeat.prototype.call = function call(context, changes) { @@ -69,21 +70,20 @@ var Repeat = (function () { Repeat.prototype.bind = function bind(bindingContext, overrideContext) { var items = this.items; + this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); + this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; if (items === undefined || items === null) { return; } - - this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); - this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; - this.collectionStrategy = this.collectionStrategyLocator.getStrategy(this.items); - this.collectionStrategy.initialize(this, bindingContext, overrideContext); this.processItems(); }; Repeat.prototype.unbind = function unbind() { this.sourceExpression = null; this.scope = null; - this.collectionStrategy.dispose(); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); + } this.items = null; this.collectionStrategy = null; this.viewSlot.removeAll(true); @@ -106,17 +106,27 @@ var Repeat = (function () { var _this = this; var items = this.items; - var rmPromise = undefined; - if (this.collectionObserver) { - this.unsubscribeCollection(); - rmPromise = this.viewSlot.removeAll(true); + this.unsubscribeCollection(); + var rmPromise = this.viewSlot.removeAll(true); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); } if (!items && items !== 0) { return; } + var bindingContext = undefined; + var overrideContext = undefined; + if (this.scope) { + bindingContext = this.scope.bindingContext; + overrideContext = this.scope.overrideContext; + } + + this.collectionStrategy = this.collectionStrategyLocator.getStrategy(items); + this.collectionStrategy.initialize(this, bindingContext, overrideContext); + if (rmPromise instanceof Promise) { rmPromise.then(function () { _this.processItemsByStrategy(); @@ -169,7 +179,17 @@ var Repeat = (function () { }; Repeat.prototype.handleInnerCollectionChanges = function handleInnerCollectionChanges(collection, changes) { + var _this2 = this; + + if (this.ignoreMutation) { + return; + } + this.ignoreMutation = true; var newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); + this.observerLocator.taskQueue.queueMicroTask(function () { + return _this2.ignoreMutation = false; + }); + if (newItems === this.items) { return; } diff --git a/dist/es6/compose.js b/dist/es6/compose.js index c135cc8..da8ac0d 100644 --- a/dist/es6/compose.js +++ b/dist/es6/compose.js @@ -58,9 +58,11 @@ export class Compose { * * @method bind * @param {bindingContext} bindingContext The context in which the view model is executed in + * @param {overrideContext} overrideContext The context in which the view model is executed in */ - bind(bindingContext) { - this.$parent = bindingContext; + bind(bindingContext, overrideContext) { + this.bindingContext = bindingContext; + this.overrideContext = overrideContext; processInstruction(this, createInstruction(this, { view: this.view, viewModel: this.viewModel, @@ -68,6 +70,14 @@ export class Compose { })); } + unbind(bindingContext, overrideContext) { + this.bindingContext = null; + this.overrideContext = null; + let returnToCache = true; + let skipAnimation = true; + this.viewSlot.removeAll(returnToCache, skipAnimation); + } + modelChanged(newValue, oldValue) { if (this.currentInstruction) { this.currentInstruction.model = newValue; @@ -123,7 +133,8 @@ export class Compose { function createInstruction(composer, instruction) { return Object.assign(instruction, { - bindingContext: composer.$parent, + bindingContext: composer.bindingContext, + overrideContext: composer.overrideContext, container: composer.container, viewSlot: composer.viewSlot, viewResources: composer.viewResources, diff --git a/dist/es6/repeat.js b/dist/es6/repeat.js index 6c1ec60..a948a34 100644 --- a/dist/es6/repeat.js +++ b/dist/es6/repeat.js @@ -52,6 +52,7 @@ export class Repeat { this.key = 'key'; this.value = 'value'; this.collectionStrategyLocator = collectionStrategyLocator; + this.ignoreMutation = false; } call(context, changes) { @@ -60,21 +61,20 @@ export class Repeat { bind(bindingContext, overrideContext) { let items = this.items; + this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); + this.scope = { bindingContext, overrideContext }; if (items === undefined || items === null) { return; } - - this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); - this.scope = { bindingContext, overrideContext }; - this.collectionStrategy = this.collectionStrategyLocator.getStrategy(this.items); - this.collectionStrategy.initialize(this, bindingContext, overrideContext); this.processItems(); } unbind() { this.sourceExpression = null; this.scope = null; - this.collectionStrategy.dispose(); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); + } this.items = null; this.collectionStrategy = null; this.viewSlot.removeAll(true); @@ -95,17 +95,27 @@ export class Repeat { processItems() { let items = this.items; - let rmPromise; - if (this.collectionObserver) { - this.unsubscribeCollection(); - rmPromise = this.viewSlot.removeAll(true); + this.unsubscribeCollection(); + let rmPromise = this.viewSlot.removeAll(true); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); } if (!items && items !== 0) { return; } + let bindingContext; + let overrideContext; + if (this.scope) { + bindingContext = this.scope.bindingContext; + overrideContext = this.scope.overrideContext; + } + + this.collectionStrategy = this.collectionStrategyLocator.getStrategy(items); + this.collectionStrategy.initialize(this, bindingContext, overrideContext); + if (rmPromise instanceof Promise) { rmPromise.then(() => { this.processItemsByStrategy(); @@ -158,7 +168,16 @@ export class Repeat { } handleInnerCollectionChanges(collection, changes) { + // guard against source expressions that have observable side-effects that could + // cause an infinite loop- eg a value converter that mutates the source array. + if (this.ignoreMutation) { + return; + } + this.ignoreMutation = true; let newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); + this.observerLocator.taskQueue.queueMicroTask(() => this.ignoreMutation = false); + + // collection change? if (newItems === this.items) { return; } diff --git a/dist/system/compose.js b/dist/system/compose.js index c09fc01..6727901 100644 --- a/dist/system/compose.js +++ b/dist/system/compose.js @@ -11,7 +11,8 @@ System.register(['aurelia-dependency-injection', 'aurelia-task-queue', 'aurelia- function createInstruction(composer, instruction) { return Object.assign(instruction, { - bindingContext: composer.$parent, + bindingContext: composer.bindingContext, + overrideContext: composer.overrideContext, container: composer.container, viewSlot: composer.viewSlot, viewResources: composer.viewResources, @@ -83,8 +84,9 @@ System.register(['aurelia-dependency-injection', 'aurelia-task-queue', 'aurelia- this.currentViewModel = null; } - Compose.prototype.bind = function bind(bindingContext) { - this.$parent = bindingContext; + Compose.prototype.bind = function bind(bindingContext, overrideContext) { + this.bindingContext = bindingContext; + this.overrideContext = overrideContext; processInstruction(this, createInstruction(this, { view: this.view, viewModel: this.viewModel, @@ -92,6 +94,14 @@ System.register(['aurelia-dependency-injection', 'aurelia-task-queue', 'aurelia- })); }; + Compose.prototype.unbind = function unbind(bindingContext, overrideContext) { + this.bindingContext = null; + this.overrideContext = null; + var returnToCache = true; + var skipAnimation = true; + this.viewSlot.removeAll(returnToCache, skipAnimation); + }; + Compose.prototype.modelChanged = function modelChanged(newValue, oldValue) { var _this = this; diff --git a/dist/system/repeat.js b/dist/system/repeat.js index 50c3619..ca9011a 100644 --- a/dist/system/repeat.js +++ b/dist/system/repeat.js @@ -91,6 +91,7 @@ System.register(['aurelia-dependency-injection', 'aurelia-binding', 'aurelia-tem this.key = 'key'; this.value = 'value'; this.collectionStrategyLocator = collectionStrategyLocator; + this.ignoreMutation = false; } Repeat.prototype.call = function call(context, changes) { @@ -99,21 +100,20 @@ System.register(['aurelia-dependency-injection', 'aurelia-binding', 'aurelia-tem Repeat.prototype.bind = function bind(bindingContext, overrideContext) { var items = this.items; + this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); + this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; if (items === undefined || items === null) { return; } - - this.sourceExpression = getSourceExpression(this.instruction, 'repeat.for'); - this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; - this.collectionStrategy = this.collectionStrategyLocator.getStrategy(this.items); - this.collectionStrategy.initialize(this, bindingContext, overrideContext); this.processItems(); }; Repeat.prototype.unbind = function unbind() { this.sourceExpression = null; this.scope = null; - this.collectionStrategy.dispose(); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); + } this.items = null; this.collectionStrategy = null; this.viewSlot.removeAll(true); @@ -136,17 +136,27 @@ System.register(['aurelia-dependency-injection', 'aurelia-binding', 'aurelia-tem var _this = this; var items = this.items; - var rmPromise = undefined; - if (this.collectionObserver) { - this.unsubscribeCollection(); - rmPromise = this.viewSlot.removeAll(true); + this.unsubscribeCollection(); + var rmPromise = this.viewSlot.removeAll(true); + if (this.collectionStrategy) { + this.collectionStrategy.dispose(); } if (!items && items !== 0) { return; } + var bindingContext = undefined; + var overrideContext = undefined; + if (this.scope) { + bindingContext = this.scope.bindingContext; + overrideContext = this.scope.overrideContext; + } + + this.collectionStrategy = this.collectionStrategyLocator.getStrategy(items); + this.collectionStrategy.initialize(this, bindingContext, overrideContext); + if (rmPromise instanceof Promise) { rmPromise.then(function () { _this.processItemsByStrategy(); @@ -199,7 +209,17 @@ System.register(['aurelia-dependency-injection', 'aurelia-binding', 'aurelia-tem }; Repeat.prototype.handleInnerCollectionChanges = function handleInnerCollectionChanges(collection, changes) { + var _this2 = this; + + if (this.ignoreMutation) { + return; + } + this.ignoreMutation = true; var newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); + this.observerLocator.taskQueue.queueMicroTask(function () { + return _this2.ignoreMutation = false; + }); + if (newItems === this.items) { return; } diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 4ced738..38083e9 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,3 +1,14 @@ +### 0.17.1 (2015-11-11) + + +#### Bug Fixes + +* **compose:** preserve access to parent scope ([a551ce46](http://github.com/aurelia/templating-resources/commit/a551ce46b6ef50b7aef54266e31517c357d1ce32), closes [#145](http://github.com/aurelia/templating-resources/issues/145)) +* **repeat:** + * handle evaluate causing side-effects ([7e2a2b0b](http://github.com/aurelia/templating-resources/commit/7e2a2b0bdfce17bf38b80c12d593bcc5fb8a086c)) + * handle collection instance changes ([738ea609](http://github.com/aurelia/templating-resources/commit/738ea609494c718f58d0a43b610bb9a26ff90d92), closes [#144](http://github.com/aurelia/templating-resources/issues/144)) + + ## 0.17.0 (2015-11-10) diff --git a/package.json b/package.json index e2506ad..2cab3ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aurelia-templating-resources", - "version": "0.17.0", + "version": "0.17.1", "description": "A standard set of behaviors, converters and other resources for use with the Aurelia templating library.", "keywords": [ "aurelia",