diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index e469aac3e2c..fb0ece11b1b 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -181,6 +181,7 @@ var ContainerDebugAdapter; */ var Application = Namespace.extend(DeferredMixin, { + _suppressDeferredDeprecation: true, /** The root DOM element of the Application. This can be specified as an @@ -760,6 +761,17 @@ var Application = Namespace.extend(DeferredMixin, { initializer: function(options) { this.constructor.initializer(options); + }, + + /** + @method then + @private + @deprecated + */ + then: function() { + Ember.deprecate('Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead.'); + + this._super.apply(this, arguments); } }); diff --git a/packages/ember-application/tests/system/application_test.js b/packages/ember-application/tests/system/application_test.js index ba2d9f320fd..6b1ee3008da 100644 --- a/packages/ember-application/tests/system/application_test.js +++ b/packages/ember-application/tests/system/application_test.js @@ -284,3 +284,15 @@ test("can resolve custom router", function(){ ok(app.__container__.lookup('router:main') instanceof CustomRouter, 'application resolved the correct router'); }); + +test("throws helpful error if `app.then` is used", function() { + run(function() { + app = Application.create({ + rootElement: '#qunit-fixture' + }); + }); + + expectDeprecation(function() { + run(app, 'then', Ember.K); + }, /Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead./); +}); diff --git a/packages/ember-application/tests/system/readiness_test.js b/packages/ember-application/tests/system/readiness_test.js index 093cfa0b9ac..470c64e88da 100644 --- a/packages/ember-application/tests/system/readiness_test.js +++ b/packages/ember-application/tests/system/readiness_test.js @@ -60,57 +60,37 @@ QUnit.module("Application readiness", { // it was triggered after initialization. test("Ember.Application's ready event is called right away if jQuery is already ready", function() { - var wasResolved = 0; jQuery.isReady = true; run(function() { application = Application.create({ router: false }); - application.then(function() { - wasResolved++; - }); equal(readyWasCalled, 0, "ready is not called until later"); - equal(wasResolved, 0); }); - equal(wasResolved, 1); equal(readyWasCalled, 1, "ready was called"); domReady(); - equal(wasResolved, 1); equal(readyWasCalled, 1, "application's ready was not called again"); }); test("Ember.Application's ready event is called after the document becomes ready", function() { - var wasResolved = 0; run(function() { application = Application.create({ router: false }); - application.then(function() { - wasResolved++; - }); - equal(wasResolved, 0); }); equal(readyWasCalled, 0, "ready wasn't called yet"); - equal(wasResolved, 0); domReady(); - equal(wasResolved, 1); equal(readyWasCalled, 1, "ready was called now that DOM is ready"); }); test("Ember.Application's ready event can be deferred by other components", function() { - var wasResolved = 0; - run(function() { application = Application.create({ router: false }); - application.then(function() { - wasResolved++; - }); application.deferReadiness(); - equal(wasResolved, 0); }); equal(readyWasCalled, 0, "ready wasn't called yet"); @@ -118,29 +98,22 @@ test("Ember.Application's ready event can be deferred by other components", func domReady(); equal(readyWasCalled, 0, "ready wasn't called yet"); - equal(wasResolved, 0); run(function() { application.advanceReadiness(); equal(readyWasCalled, 0); - equal(wasResolved, 0); }); - equal(wasResolved, 1); equal(readyWasCalled, 1, "ready was called now all readiness deferrals are advanced"); }); test("Ember.Application's ready event can be deferred by other components", function() { - var wasResolved = 0; jQuery.isReady = false; run(function() { application = Application.create({ router: false }); application.deferReadiness(); - application.then(function() { - wasResolved++; - }); - equal(wasResolved, 0); + equal(readyWasCalled, 0, "ready wasn't called yet"); }); domReady(); @@ -149,10 +122,8 @@ test("Ember.Application's ready event can be deferred by other components", func run(function() { application.advanceReadiness(); - equal(wasResolved, 0); }); - equal(wasResolved, 1); equal(readyWasCalled, 1, "ready was called now all readiness deferrals are advanced"); expectAssertion(function() { diff --git a/packages/ember-application/tests/system/reset_test.js b/packages/ember-application/tests/system/reset_test.js index be7c3bc6ec6..2021fa869e3 100644 --- a/packages/ember-application/tests/system/reset_test.js +++ b/packages/ember-application/tests/system/reset_test.js @@ -29,12 +29,13 @@ QUnit.module("Ember.Application - resetting", { test("Brings it's own run-loop if not provided", function() { application = run(Application, 'create'); + application.ready = function() { + QUnit.start(); + ok(true, 'app booted'); + }; + QUnit.stop(); application.reset(); - - run(application,'then', function() { - ok(true, 'app booted'); - }); }); test("does not bring it's own run loop if one is already provided", function() { diff --git a/packages/ember-runtime/lib/ext/rsvp.js b/packages/ember-runtime/lib/ext/rsvp.js index 5be74e594bf..843da45ea47 100644 --- a/packages/ember-runtime/lib/ext/rsvp.js +++ b/packages/ember-runtime/lib/ext/rsvp.js @@ -2,10 +2,39 @@ import Ember from 'ember-metal/core'; import Logger from 'ember-metal/logger'; +import run from "ember-metal/run_loop"; var RSVP = requireModule('rsvp'); var Test, testModuleName = 'ember-testing/test'; +var asyncStart = function() { + if (Ember.Test && Ember.Test.adapter) { + Ember.Test.adapter.asyncStart(); + } +}; + +var asyncEnd = function() { + if (Ember.Test && Ember.Test.adapter) { + Ember.Test.adapter.asyncEnd(); + } +}; + +RSVP.configure('async', function(callback, promise) { + var async = !run.currentRunLoop; + + if (Ember.testing && async) { asyncStart(); } + + run.backburner.schedule('actions', function(){ + if (Ember.testing && async) { asyncEnd(); } + callback(promise); + }); +}); + +RSVP.Promise.prototype.fail = function(callback, label){ + Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch'); + return this['catch'](callback, label); +}; + RSVP.onerrorDefault = function (error) { if (error instanceof Error) { if (Ember.testing) { diff --git a/packages/ember-runtime/lib/mixins/deferred.js b/packages/ember-runtime/lib/mixins/deferred.js index 4d67f34c8fc..da222bde09d 100644 --- a/packages/ember-runtime/lib/mixins/deferred.js +++ b/packages/ember-runtime/lib/mixins/deferred.js @@ -2,37 +2,8 @@ import Ember from "ember-metal/core"; // Ember.FEATURES, Ember.Test import { get } from "ember-metal/property_get"; import { Mixin } from "ember-metal/mixin"; import { computed } from "ember-metal/computed"; -import run from "ember-metal/run_loop"; import RSVP from "ember-runtime/ext/rsvp"; -var asyncStart = function() { - if (Ember.Test && Ember.Test.adapter) { - Ember.Test.adapter.asyncStart(); - } -}; - -var asyncEnd = function() { - if (Ember.Test && Ember.Test.adapter) { - Ember.Test.adapter.asyncEnd(); - } -}; - -RSVP.configure('async', function(callback, promise) { - var async = !run.currentRunLoop; - - if (Ember.testing && async) { asyncStart(); } - - run.backburner.schedule('actions', function(){ - if (Ember.testing && async) { asyncEnd(); } - callback(promise); - }); -}); - -RSVP.Promise.prototype.fail = function(callback, label){ - Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch'); - return this['catch'](callback, label); -}; - /** @module ember @submodule ember-runtime @@ -97,6 +68,8 @@ export default Mixin.create({ }, _deferred: computed(function() { + Ember.deprecate('Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.', this._suppressDeferredDeprecation); + return RSVP.defer('Ember: DeferredMixin - ' + this); }) }); diff --git a/packages/ember-runtime/lib/system/deferred.js b/packages/ember-runtime/lib/system/deferred.js index 6d47753a168..81be96a3211 100644 --- a/packages/ember-runtime/lib/system/deferred.js +++ b/packages/ember-runtime/lib/system/deferred.js @@ -1,8 +1,14 @@ +import Ember from 'ember-metal/core'; import DeferredMixin from "ember-runtime/mixins/deferred"; import {get} from "ember-metal/property_get"; import EmberObject from "ember-runtime/system/object"; -var Deferred = EmberObject.extend(DeferredMixin); +var Deferred = EmberObject.extend(DeferredMixin, { + init: function() { + Ember.deprecate('Usage of Ember.Deferred is deprecated.'); + this._super(); + } +}); Deferred.reopenClass({ promise: function(callback, binding) { diff --git a/packages/ember-runtime/tests/ext/rsvp_test.js b/packages/ember-runtime/tests/ext/rsvp_test.js index 026c90bdd7c..1f662d22733 100644 --- a/packages/ember-runtime/tests/ext/rsvp_test.js +++ b/packages/ember-runtime/tests/ext/rsvp_test.js @@ -1,3 +1,5 @@ +/* global Promise:true */ + import run from "ember-metal/run_loop"; import RSVP from "ember-runtime/ext/rsvp"; @@ -17,3 +19,92 @@ test('Ensure that errors thrown from within a promise are sent to the console', equal(e, error, "error was re-thrown"); } }); + +var asyncStarted = 0; +var asyncEnded = 0; +var Promise = RSVP.Promise; + +var EmberTest; +var EmberTesting; + +QUnit.module("Deferred RSVP's async + Testing", { + setup: function() { + EmberTest = Ember.Test; + EmberTesting = Ember.testing; + + Ember.Test = { + adapter: { + asyncStart: function() { + asyncStarted++; + QUnit.stop(); + }, + asyncEnd: function() { + asyncEnded++; + QUnit.start(); + } + } + }; + }, + teardown: function() { + asyncStarted = 0; + asyncEnded = 0; + + Ember.testing = EmberTesting; + Ember.Test = EmberTest; + } +}); + +test("given `Ember.testing = true`, correctly informs the test suite about async steps", function() { + expect(19); + + ok(!run.currentRunLoop, 'expect no run-loop'); + + Ember.testing = true; + + equal(asyncStarted, 0); + equal(asyncEnded, 0); + + var user = Promise.resolve({ + name: 'tomster' + }); + + equal(asyncStarted, 0); + equal(asyncEnded, 0); + + user.then(function(user){ + equal(asyncStarted, 1); + equal(asyncEnded, 1); + + equal(user.name, 'tomster'); + + return Promise.resolve(1).then(function(){ + equal(asyncStarted, 1); + equal(asyncEnded, 1); + }); + + }).then(function(){ + equal(asyncStarted, 1); + equal(asyncEnded, 1); + + return new Promise(function(resolve){ + QUnit.stop(); // raw async, we must inform the test framework manually + setTimeout(function(){ + QUnit.start(); // raw async, we must inform the test framework manually + + equal(asyncStarted, 1); + equal(asyncEnded, 1); + + resolve({ + name: 'async tomster' + }); + + equal(asyncStarted, 2); + equal(asyncEnded, 1); + }, 0); + }); + }).then(function(user){ + equal(user.name, 'async tomster'); + equal(asyncStarted, 2); + equal(asyncEnded, 2); + }); +}); diff --git a/packages/ember-runtime/tests/mixins/deferred_test.js b/packages/ember-runtime/tests/mixins/deferred_test.js index d805c21787b..74e2fb80194 100644 --- a/packages/ember-runtime/tests/mixins/deferred_test.js +++ b/packages/ember-runtime/tests/mixins/deferred_test.js @@ -1,4 +1,4 @@ -/* global Promise:true */ +/* global Promise:true,EmberDev */ import Ember from 'ember-metal/core'; import run from 'ember-metal/run_loop'; @@ -6,7 +6,18 @@ import EmberObject from 'ember-runtime/system/object'; import Deferred from "ember-runtime/mixins/deferred"; import RSVP from "ember-runtime/ext/rsvp"; -QUnit.module("Deferred"); +var originalDeprecate; + +QUnit.module("Deferred", { + setup: function() { + originalDeprecate = Ember.deprecate; + Ember.deprecate = function() { }; + }, + + teardown: function() { + Ember.deprecate = originalDeprecate; + } +}); test("can resolve deferred", function() { var deferred, count = 0; @@ -320,91 +331,22 @@ test("can handle fulfillment without fulfillment handler", function() { run(deferred, 'resolve', fulfillment); }); -var asyncStarted = 0; -var asyncEnded = 0; -var Promise = RSVP.Promise; - -var EmberTest; -var EmberTesting; +if (!EmberDev.runningProdBuild){ + test("causes a deprecation warning when used", function() { + var deferred, deprecationMade, obj = {}; -QUnit.module("Deferred RSVP's async + Testing", { - setup: function() { - EmberTest = Ember.Test; - EmberTesting = Ember.testing; - - Ember.Test = { - adapter: { - asyncStart: function() { - asyncStarted++; - QUnit.stop(); - }, - asyncEnd: function() { - asyncEnded++; - QUnit.start(); - } - } + Ember.deprecate = function(message) { + deprecationMade = message; }; - }, - teardown: function() { - asyncStarted = 0; - asyncEnded = 0; - - Ember.testing = EmberTesting; - Ember.Test = EmberTest; - } -}); -test("given `Ember.testing = true`, correctly informs the test suite about async steps", function() { - expect(19); - - ok(!run.currentRunLoop, 'expect no run-loop'); - - Ember.testing = true; - - equal(asyncStarted, 0); - equal(asyncEnded, 0); - - var user = Promise.resolve({ - name: 'tomster' - }); - - equal(asyncStarted, 0); - equal(asyncEnded, 0); - - user.then(function(user){ - equal(asyncStarted, 1); - equal(asyncEnded, 1); - - equal(user.name, 'tomster'); + deferred = EmberObject.createWithMixins(Deferred); + equal(deprecationMade, undefined, 'no deprecation was made on init'); - return Promise.resolve(1).then(function(){ - equal(asyncStarted, 1); - equal(asyncEnded, 1); + deferred.then(function(value) { + equal(value, obj, "successfully resolved to given value"); }); + equal(deprecationMade, 'Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.'); - }).then(function(){ - equal(asyncStarted, 1); - equal(asyncEnded, 1); - - return new Promise(function(resolve){ - QUnit.stop(); // raw async, we must inform the test framework manually - setTimeout(function(){ - QUnit.start(); // raw async, we must inform the test framework manually - - equal(asyncStarted, 1); - equal(asyncEnded, 1); - - resolve({ - name: 'async tomster' - }); - - equal(asyncStarted, 2); - equal(asyncEnded, 1); - }, 0); - }); - }).then(function(user){ - equal(user.name, 'async tomster'); - equal(asyncStarted, 2); - equal(asyncEnded, 2); + run(deferred, 'resolve', obj); }); -}); +} diff --git a/packages/ember-runtime/tests/system/deferred_test.js b/packages/ember-runtime/tests/system/deferred_test.js index 3010afcacbb..4ff023a3a2d 100644 --- a/packages/ember-runtime/tests/system/deferred_test.js +++ b/packages/ember-runtime/tests/system/deferred_test.js @@ -7,29 +7,33 @@ QUnit.module("Ember.Deferred all-in-one"); asyncTest("Can resolve a promise", function() { var value = { value: true }; - var promise = Deferred.promise(function(deferred) { - setTimeout(function() { - run(function() { deferred.resolve(value); }); + ignoreDeprecation(function() { + var promise = Deferred.promise(function(deferred) { + setTimeout(function() { + run(function() { deferred.resolve(value); }); + }); }); - }); - promise.then(function(resolveValue) { - QUnit.start(); - equal(resolveValue, value, "The resolved value should be correct"); + promise.then(function(resolveValue) { + QUnit.start(); + equal(resolveValue, value, "The resolved value should be correct"); + }); }); }); asyncTest("Can reject a promise", function() { var rejected = { rejected: true }; - var promise = Deferred.promise(function(deferred) { - setTimeout(function() { - run(function() { deferred.reject(rejected); }); + ignoreDeprecation(function() { + var promise = Deferred.promise(function(deferred) { + setTimeout(function() { + run(function() { deferred.reject(rejected); }); + }); }); - }); - promise.then(null, function(rejectedValue) { - QUnit.start(); - equal(rejectedValue, rejected, "The resolved value should be correct"); + promise.then(null, function(rejectedValue) { + QUnit.start(); + equal(rejectedValue, rejected, "The resolved value should be correct"); + }); }); }); diff --git a/packages/ember/tests/routing/basic_test.js b/packages/ember/tests/routing/basic_test.js index ef9527cde93..0fdd8f53e70 100644 --- a/packages/ember/tests/routing/basic_test.js +++ b/packages/ember/tests/routing/basic_test.js @@ -755,16 +755,16 @@ test("The Special Page returning a promise puts the app into a loading state unt this.resource("special", { path: "/specials/:menu_item_id" }); }); - var menuItem; + var menuItem, resolve; - App.MenuItem = Ember.Object.extend(Ember.DeferredMixin); + App.MenuItem = Ember.Object.extend(); App.MenuItem.reopenClass({ find: function(id) { - menuItem = App.MenuItem.create({ - id: id - }); + menuItem = App.MenuItem.create({ id: id }); - return menuItem; + return new Ember.RSVP.Promise(function(res) { + resolve = res; + }); } }); @@ -795,7 +795,7 @@ test("The Special Page returning a promise puts the app into a loading state unt equal(Ember.$('p', '#qunit-fixture').text(), "LOADING!", "The app is in the loading state"); Ember.run(function() { - menuItem.resolve(menuItem); + resolve(menuItem); }); equal(Ember.$('p', '#qunit-fixture').text(), "1", "The app is now in the specials state"); @@ -885,13 +885,17 @@ test("The Special page returning an error invokes SpecialRoute's error handler", this.resource("special", { path: "/specials/:menu_item_id" }); }); - var menuItem; + var menuItem, promise, resolve; - App.MenuItem = Ember.Object.extend(Ember.DeferredMixin); + App.MenuItem = Ember.Object.extend(); App.MenuItem.reopenClass({ find: function(id) { menuItem = App.MenuItem.create({ id: id }); - return menuItem; + promise = new Ember.RSVP.Promise(function(res) { + resolve = res; + }); + + return promise; } }); @@ -910,7 +914,9 @@ test("The Special page returning an error invokes SpecialRoute's error handler", handleURLRejectsWith('/specials/1', 'Setup error'); - Ember.run(menuItem, menuItem.resolve, menuItem); + Ember.run(function() { + resolve(menuItem); + }); }); function testOverridableErrorHandler(handlersName) { @@ -922,13 +928,15 @@ function testOverridableErrorHandler(handlersName) { this.resource("special", { path: "/specials/:menu_item_id" }); }); - var menuItem; + var menuItem, resolve; - App.MenuItem = Ember.Object.extend(Ember.DeferredMixin); + App.MenuItem = Ember.Object.extend(); App.MenuItem.reopenClass({ find: function(id) { menuItem = App.MenuItem.create({ id: id }); - return menuItem; + return new Ember.RSVP.Promise(function(res) { + resolve = res; + }); } }); @@ -951,7 +959,9 @@ function testOverridableErrorHandler(handlersName) { handleURLRejectsWith("/specials/1", "Setup error"); - Ember.run(menuItem, 'resolve', menuItem); + Ember.run(function() { + resolve(menuItem); + }); } test("ApplicationRoute's default error handler can be overridden", function() { @@ -970,7 +980,7 @@ asyncTest("Moving from one page to another triggers the correct callbacks", func this.resource("special", { path: "/specials/:menu_item_id" }); }); - App.MenuItem = Ember.Object.extend(Ember.DeferredMixin); + App.MenuItem = Ember.Object.extend(); App.SpecialRoute = Ember.Route.extend({ setupController: function(controller, model) { @@ -998,7 +1008,7 @@ asyncTest("Moving from one page to another triggers the correct callbacks", func var promiseContext = App.MenuItem.create({ id: 1 }); Ember.run.later(function() { - promiseContext.resolve(promiseContext); + Ember.RSVP.resolve(promiseContext); }, 1); return router.transitionTo('special', promiseContext); @@ -1024,9 +1034,9 @@ asyncTest("Nested callbacks are not exited when moving to siblings", function() }) }); - var menuItem; + var menuItem, resolve; - App.MenuItem = Ember.Object.extend(Ember.DeferredMixin); + App.MenuItem = Ember.Object.extend(); App.MenuItem.reopenClass({ find: function(id) { menuItem = App.MenuItem.create({ id: id }); @@ -1096,7 +1106,9 @@ asyncTest("Nested callbacks are not exited when moving to siblings", function() Ember.run(function() { var menuItem = App.MenuItem.create({ id: 1 }); - Ember.run.later(function() { menuItem.resolve(menuItem); }, 1); + Ember.run.later(function() { + Ember.RSVP.resolve(menuItem); + }, 1); router.transitionTo('special', menuItem).then(function(result) { equal(rootSetup, 1, "The root setup was not triggered again");