Ember 1.3.0 and 1.4 Beta Released


We are pleased to announce that both Ember.js 1.3.0 and the first beta in the 1.4 series
have been released. This comes as the third cycle of our six-week release
process that began after 1.0 was released.
New in 1.3
Non-array Dependencies for ReduceComputed
Generally, using reduceComputed is all about efficiently computing the resulting value, but
occasionally you might need to recompute every time. It is now possible to instruct
reduceComputed to completely recompute when an item is added/removed (instead of calling
the addedItem and removedItem callbacks).
This is done by using either non-array dependent keys or adding .[] to an array dependency.
Take a look at the following example:
Ember.Object.extend({
// When `string` is changed, `computed` is completely recomputed.
string: 'a string',

// When an item is added to `array`, `addedItem` is called.
array: [],

// When an item is added to `anotherArray`, `computed` is completely
// recomputed.
anotherArray: [],

computed: Ember.reduceComputed('string', 'array', 'anotherArray.[]', {
addedItem: addedItemCallback,
removedItem: removedItemCallback
})
});

Testing
Testability of Ember applications is an ongoing priority, and the 1.3 release
contains a number of updates that result in a dramatic improvement.
Custom wait() Hooks
You can now specify custom hooks to notify the asynchronous test helpers when all
async actions have completed. Under Ember 1.2 if you need to wait for an IndexDB
action, the default wait implementation would not wait until that
action finished. Now you can register your own hook that will instruct wait
that it is truly time to continue.
For example:
Ember.Test.registerWaiter(function() {
return hasPendingTransactions() == 0;
});

This instructs the wait helper that the async actions are not finished until
hasPendingTransactions is zero.
You can find more details here.
Lazy Routing
Under Ember.js 1.2 routing is started as soon as you boot your application and before
you call visit. This results in duplicate routing which slows down your tests and also
potentially causes your tests to be less isolated.
Under Ember.js 1.3 routing isn't started until you call visit for the first time. This
provides a couple of improvements to the way you test:

  • You do not need to call App.advanceReadiness() in your test setup since the application
    is automatically in a deferred state until calling visit.
  • App.reset() now leaves the application in the same state as App.setupForTesting() (a
    deferred state).

You can find more details here.
Stubbable controllers Property

Prior to Ember 1.3 you could not easily stub out any dependencies specified with needs.
Now you can unit test controllers and stub their dependencies all within
TheControllerClass.create() instead of having to use a container, register stubbed
dependencies, and instantiate the controller via container.lookup().
Simplified example:
var BrotherController = Ember.Controller.extend({
needs: 'sister',
foo: Ember.computed.alias('controllers.sister.foo')
});

var broController = BrotherController.create({
controllers: {
sister: { foo: 5 }
}
});

equal(broController.get('foo'), 5, "`needs` dependencies can be stubbed");

Previously, specifying controllers to BrotherController would have resulted in an error,
and now under Ember.js 1.3 this works as expected.
Promise Improvements
Ember.js 1.3 has updated to RSVP 3.0.3 which brings considerable performance improvements, a number
of new features, and significantly improved documentation coverage.
RSVP has added a number of features that allow external tooling to be able to inspect and track the labels, states, and
values of promises. These improvements will be extremely useful when used with the next major
version of the Ember Inspector.
Which will allow you to see a tree of promises and inspect their names, state, and fulfilled/rejected values.
RSVP added a number of additional methods to Promise:

  • Promise.cast - Coerces the given argument into a promise, or returns the argument if it is
    already a promise.
  • Promise.catch - catch is essentially syntactic sugar for then(undefined, onRejection) which
    makes it the same as the catch block of a try/catch statement.
  • Promise.finally - The callback provided to Promise.finally will be invoked regardless of the
    promises fate (both fulfilled and rejected promises). This is essentially similar to native
    try/catch/finally statements.
  • Promise.race - Will return a new promise which will be settled with the value of
    the first promise that settles. In other words: given an array of promises Promise.race
    will return the value from the first argument that settles (like the winner in a "race").

Please review the documentation for more information.
Other Improvements
As usual, there are a ton of bug fixes and small improvements in this
release. You can see a list of all the changes in the CHANGELOG: