From c2bcc86a15632b78a8f1f5c56e10981bfa539e66 Mon Sep 17 00:00:00 2001 From: Cory Forsyth Date: Thu, 11 Jun 2015 15:33:27 -0400 Subject: [PATCH] [BUGFIX beta] Deprecate {{view "string"}} and special case {{view "select"}} Use a template-compiler plugin to detect `{{view "string"}}` at compile-time and issue a deprecation with location information. Has a special case deprecation when the string === "select". Removes a test from the view helper tests that was checking for the deprecation at runtime (and removes the associated code in the ember-htmlbars package's `keywords/view`). Note: This does not catch a deprecation when the path is not a string, e.g., `{{view view.someProperty}}`, however #11401 would catch and issue a deprecation message for that case (at runtime). Also a few changes to deprecations: * document `id` param to `Ember.deprecate` * include deprecation id in log/error message * Use dot-namespaced deprecation ids (more similar to how `instrument` works and paves the way to in the future changing deprecation log levels by paths ie `"view.*"`) * globally silence view-related deprecations in tests to avoid overflowing travis ci's log * update ember-dev dep in bower (pr: https://github.com/emberjs/ember-dev/pull/153) to `a064f0cd2f4c225ffd023b63d4cb31a79db04aaf` * change the view-and-controller-path template compiler plugin to always deprecate `{{controller}}` * change the view-and-controller-path template compiler plugin to skip deprecating `{{view}}` when `Ember.ENV._ENABLE_LEGACY_VIW_SUPPORT` is true refs #11377 --- bower.json | 2 +- packages/ember-debug/lib/main.js | 9 ++- packages/ember-htmlbars/lib/keywords/view.js | 1 - .../tests/compat/view_helper_test.js | 72 +++++++++++++++++++ .../ember-htmlbars/tests/helpers/view_test.js | 15 ---- packages/ember-template-compiler/lib/main.js | 2 + .../deprecate-view-and-controller-paths.js | 16 +++-- .../lib/plugins/deprecate-view-helper.js | 52 ++++++++++++++ tests/index.html | 7 +- 9 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 packages/ember-htmlbars/tests/compat/view_helper_test.js create mode 100644 packages/ember-template-compiler/lib/plugins/deprecate-view-helper.js diff --git a/bower.json b/bower.json index d14486cbae4..1f1980c149e 100644 --- a/bower.json +++ b/bower.json @@ -10,6 +10,6 @@ "rsvp": "https://github.com/tildeio/rsvp.js.git#3.0.14", "router.js": "https://github.com/tildeio/router.js.git#ed45bc5c5e055af0ab875ef2c52feda792ee23e4", "dag-map": "https://github.com/krisselden/dag-map.git#e307363256fe918f426e5a646cb5f5062d3245be", - "ember-dev": "https://github.com/emberjs/ember-dev.git#1a1ef3e1806be21dd554d285521abc0b13cdfe20" + "ember-dev": "https://github.com/emberjs/ember-dev.git#a064f0cd2f4c225ffd023b63d4cb31a79db04aaf" } } diff --git a/packages/ember-debug/lib/main.js b/packages/ember-debug/lib/main.js index 4bb376c49cf..cba1d23e1fd 100644 --- a/packages/ember-debug/lib/main.js +++ b/packages/ember-debug/lib/main.js @@ -104,7 +104,10 @@ Ember.debug = function(message) { will be displayed. If this is a function, it will be executed and its return value will be used as condition. @param {Object} options An optional object that can be used to pass - in a `url` to the transition guide on the emberjs.com website. + in a `url` to the transition guide on the emberjs.com website, and a unique + `id` for this deprecation. The `id` can be used by Ember debugging tools + to change the behavior (raise, log or silence) for that specific deprecation. + The `id` should be namespaced by dots, e.g. "view.helper.select". @public */ Ember.deprecate = function(message, test, options) { @@ -122,6 +125,10 @@ Ember.deprecate = function(message, test, options) { if (noDeprecation) { return; } + if (options && options.id) { + message = message + ` [deprecation id: ${options.id}]`; + } + if (deprecationManager.getLevel(options && options.id) === deprecationLevels.RAISE) { throw new EmberError(message); } diff --git a/packages/ember-htmlbars/lib/keywords/view.js b/packages/ember-htmlbars/lib/keywords/view.js index 7ad40e36bfc..d7d4fae2b1d 100644 --- a/packages/ember-htmlbars/lib/keywords/view.js +++ b/packages/ember-htmlbars/lib/keywords/view.js @@ -10,7 +10,6 @@ import objectKeys from "ember-metal/keys"; export default { setupState(state, env, scope, params, hash) { - Ember.deprecate(`Using the "view" helper is deprecated.`, !!Ember.ENV._ENABLE_LEGACY_VIEW_SUPPORT, { url: 'http://emberjs.com/deprecations/v1.x/#toc_ember-view', id: 'view-helper' }); var read = env.hooks.getValue; var targetObject = read(scope.self); var viewClassOrInstance = state.viewClassOrInstance; diff --git a/packages/ember-htmlbars/tests/compat/view_helper_test.js b/packages/ember-htmlbars/tests/compat/view_helper_test.js new file mode 100644 index 00000000000..fc825be40b6 --- /dev/null +++ b/packages/ember-htmlbars/tests/compat/view_helper_test.js @@ -0,0 +1,72 @@ +import EmberComponent from "ember-views/views/component"; +import EmberView from "ember-views/views/view"; +import EmberSelectView from "ember-views/views/select"; +import { runAppend, runDestroy } from "ember-runtime/tests/utils"; +import compile from "ember-template-compiler/system/compile"; +import Registry from "container/registry"; + +let component, registry, container; + +QUnit.module('ember-htmlbars: compat - view helper', { + setup() { + registry = new Registry(); + container = registry.container(); + }, + teardown() { + runDestroy(component); + runDestroy(container); + registry = container = component = null; + } +}); + +QUnit.test('using the view helper with a string (inline form) is deprecated [DEPRECATED]', function(assert) { + const ViewClass = EmberView.extend({ + template: compile('fooView') + }); + registry.register('view:foo', ViewClass); + + expectDeprecation(function() { + component = EmberComponent.extend({ + layout: compile("{{view 'foo'}}"), + container + }).create(); + + runAppend(component); + }, /Using the `{{view "string"}}` helper is deprecated/); + + assert.equal(component.$().text(), 'fooView', 'view helper is still rendered'); +}); + +QUnit.test('using the view helper with a string (block form) is deprecated [DEPRECATED]', function(assert) { + const ViewClass = EmberView.extend({ + template: compile('Foo says: {{yield}}') + }); + registry.register('view:foo', ViewClass); + + expectDeprecation(function() { + component = EmberComponent.extend({ + layout: compile("{{#view 'foo'}}I am foo{{/view}}"), + container + }).create(); + + runAppend(component); + }, /Using the `{{view "string"}}` helper is deprecated/); + + assert.equal(component.$().text(), 'Foo says: I am foo', 'view helper is still rendered'); +}); + +QUnit.test('using the view helper with string "select" has its own deprecation message [DEPRECATED]', function(assert) { + registry.register('view:select', EmberSelectView); + + expectDeprecation(function() { + component = EmberComponent.extend({ + layout: compile("{{view 'select'}}"), + container + }).create(); + + runAppend(component); + }, /Using `{{view "select"}}` is deprecated/); + + assert.ok(!!component.$('select').length, 'still renders select'); +}); + diff --git a/packages/ember-htmlbars/tests/helpers/view_test.js b/packages/ember-htmlbars/tests/helpers/view_test.js index 2455f71ff60..77523bcc2b5 100644 --- a/packages/ember-htmlbars/tests/helpers/view_test.js +++ b/packages/ember-htmlbars/tests/helpers/view_test.js @@ -143,21 +143,6 @@ QUnit.test("View lookup - App.FuView (DEPRECATED)", function() { equal(jQuery('#fu').text(), 'bro'); }); -QUnit.test("View lookup in a template using 'view' helper is deprecated", function() { - var FuView = viewClass({}); - - registry.register('view:fu', FuView); - - view = EmberView.extend({ - template: compile("{{view 'fu'}}"), - container: container - }).create(); - - expectDeprecation(function() { - runAppend(view); - }, `Using the "view" helper is deprecated.`); -}); - QUnit.test("View lookup - 'fu'", function() { var FuView = viewClass({ elementId: "fu", diff --git a/packages/ember-template-compiler/lib/main.js b/packages/ember-template-compiler/lib/main.js index b09e1ff3e19..7da2152d8cc 100644 --- a/packages/ember-template-compiler/lib/main.js +++ b/packages/ember-template-compiler/lib/main.js @@ -17,6 +17,7 @@ import TransformComponentCurlyToReadonly from "ember-template-compiler/plugins/t import TransformAngleBracketComponents from "ember-template-compiler/plugins/transform-angle-bracket-components"; import TransformInputOnToOnEvent from "ember-template-compiler/plugins/transform-input-on-to-onEvent"; import DeprecateViewAndControllerPaths from "ember-template-compiler/plugins/deprecate-view-and-controller-paths"; +import DeprecateViewHelper from "ember-template-compiler/plugins/deprecate-view-helper"; // used for adding Ember.Handlebars.compile for backwards compat import "ember-template-compiler/compat"; @@ -34,6 +35,7 @@ registerPlugin('ast', TransformComponentCurlyToReadonly); registerPlugin('ast', TransformAngleBracketComponents); registerPlugin('ast', TransformInputOnToOnEvent); registerPlugin('ast', DeprecateViewAndControllerPaths); +registerPlugin('ast', DeprecateViewHelper); export { _Ember, diff --git a/packages/ember-template-compiler/lib/plugins/deprecate-view-and-controller-paths.js b/packages/ember-template-compiler/lib/plugins/deprecate-view-and-controller-paths.js index c02fadc91b5..84e8ae3b6e1 100644 --- a/packages/ember-template-compiler/lib/plugins/deprecate-view-and-controller-paths.js +++ b/packages/ember-template-compiler/lib/plugins/deprecate-view-and-controller-paths.js @@ -13,9 +13,6 @@ function DeprecateViewAndControllerPaths(options) { @param {AST} ast The AST to be transformed. */ DeprecateViewAndControllerPaths.prototype.transform = function DeprecateViewAndControllerPaths_transform(ast) { - if (!!Ember.ENV._ENABLE_LEGACY_VIEW_SUPPORT) { - return; - } var walker = new this.syntax.Walker(); var moduleName = this.options && this.options.moduleName; @@ -55,7 +52,18 @@ function deprecatePaths(moduleName, node, paths) { } function deprecatePath(moduleName, node, path) { - Ember.deprecate(`Using \`{{${path && path.type === 'PathExpression' && path.parts[0]}}}\` or any path based on it ${calculateLocationDisplay(moduleName, node.loc)}has been deprecated.`, !(path && path.type === 'PathExpression' && (path.parts[0] === 'view' || path.parts[0] === 'controller')), { url: 'http://emberjs.com/deprecations/v1.x#toc_view-and-controller-template-keywords', id: 'view-controller-keyword' }); + Ember.deprecate(`Using \`{{${path && path.type === 'PathExpression' && path.parts[0]}}}\` or any path based on it ${calculateLocationDisplay(moduleName, node.loc)}has been deprecated.`, function deprecatePath_test() { + let noDeprecate = true; + + const viewKeyword = path && path.type === 'PathExpression' && path.parts && path.parts[0]; + if (viewKeyword === 'view') { + noDeprecate = Ember.ENV._ENABLE_LEGACY_VIEW_SUPPORT; + } else if (viewKeyword === 'controller') { + noDeprecate = false; + } + + return noDeprecate; + }, { url: 'http://emberjs.com/deprecations/v1.x#toc_view-and-controller-template-keywords', id: (path.parts && path.parts[0] === 'view' ? 'view.keyword.view' : 'view.keyword.controller') }); } function validate(node) { diff --git a/packages/ember-template-compiler/lib/plugins/deprecate-view-helper.js b/packages/ember-template-compiler/lib/plugins/deprecate-view-helper.js new file mode 100644 index 00000000000..f9aef741e53 --- /dev/null +++ b/packages/ember-template-compiler/lib/plugins/deprecate-view-helper.js @@ -0,0 +1,52 @@ +import Ember from "ember-metal/core"; +import calculateLocationDisplay from "ember-template-compiler/system/calculate-location-display"; + +function DeprecateViewHelper(options) { + // set later within HTMLBars to the syntax package + this.syntax = null; + this.options = options || {}; +} + +/** + @private + @method transform + @param {AST} ast The AST to be transformed. +*/ +DeprecateViewHelper.prototype.transform = function DeprecateViewHelper_transform(ast) { + if (!!Ember.ENV._ENABLE_LEGACY_VIEW_SUPPORT) { + return ast; + } + var walker = new this.syntax.Walker(); + var moduleName = this.options && this.options.moduleName; + + walker.visit(ast, function(node) { + if (!validate(node)) { return; } + + deprecateHelper(moduleName, node); + }); + + return ast; +}; + +function deprecateHelper(moduleName, node) { + const paramValue = node.params.length && node.params[0].value; + + if (!paramValue) { + return; + } else if (paramValue === 'select') { + deprecateSelect(moduleName, node); + } else { + Ember.deprecate(`Using the \`{{view "string"}}\` helper is deprecated. ${calculateLocationDisplay(moduleName, node.loc)}`, false, { url: 'http://emberjs.com/deprecations/v1.x#toc_ember-view', id: 'view.helper' }); + } +} + +function deprecateSelect(moduleName, node) { + Ember.deprecate(`Using \`{{view "select"}}\` is deprecated. ${calculateLocationDisplay(moduleName, node.loc)}`, false, { url: 'http://emberjs.com/deprecations/v1.x#toc_ember-select', id: 'view.helper.select' }); +} + +function validate(node) { + return (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && + (node.path.parts[0] === 'view'); +} + +export default DeprecateViewHelper; diff --git a/tests/index.html b/tests/index.html index 2486ea86e25..ca718ab752c 100644 --- a/tests/index.html +++ b/tests/index.html @@ -149,8 +149,11 @@