Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE ember-debug-handlers] #11833

Merged
merged 1 commit into from
Jul 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,8 @@ for a detailed explanation.

Implements RFC https://github.com/emberjs/rfcs/pull/58, adding support for
dashless helpers.

* `ember-debug-handlers`

Implemencts RFC https://github.com/emberjs/rfcs/pull/65, adding support for
custom deprecation and warning handlers.
3 changes: 2 additions & 1 deletion features.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"ember-routing-htmlbars-improved-actions": true,
"ember-htmlbars-get-helper": true,
"ember-htmlbars-helper": true,
"ember-htmlbars-dashless-helpers": true
"ember-htmlbars-dashless-helpers": true,
"ember-debug-handlers": null
},
"debugStatements": [
"Ember.warn",
Expand Down
93 changes: 93 additions & 0 deletions packages/ember-debug/lib/deprecate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*global __fail__*/

import Ember from 'ember-metal/core';
import EmberError from 'ember-metal/error';
import Logger from 'ember-metal/logger';
import { registerHandler as genericRegisterHandler, invoke } from 'ember-debug/handlers';

export function registerHandler(handler) {
genericRegisterHandler('deprecate', handler);
}

function formatMessage(_message, options) {
let message = _message;

if (options && options.id) {
message = message + ` [deprecation id: ${options.id}]`;
}

if (options && options.url) {
message += ' See ' + options.url + ' for more details.';
}

return message;
}

registerHandler(function logDeprecationToConsole(message, options) {
let updatedMessage = formatMessage(message, options);

Logger.warn('DEPRECATION: ' + updatedMessage);
});

registerHandler(function logDeprecationStackTrace(message, options, next) {
if (Ember.LOG_STACKTRACE_ON_DEPRECATION) {
let stackStr = '';
let error, stack;

// When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
try { __fail__.fail(); } catch (e) { error = e; }

if (error.stack) {
if (error['arguments']) {
// Chrome
stack = error.stack.replace(/^\s+at\s+/gm, '').
replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
stack.shift();
} else {
// Firefox
stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
replace(/^\(/gm, '{anonymous}(').split('\n');
}

stackStr = '\n ' + stack.slice(2).join('\n ');
}

let updatedMessage = formatMessage(message, options);

Logger.warn('DEPRECATION: ' + updatedMessage + stackStr);
} else {
next(...arguments);
}
});

registerHandler(function raiseOnDeprecation(message, options, next) {
if (Ember.ENV.RAISE_ON_DEPRECATION) {
let updatedMessage = formatMessage(message);

throw new EmberError(updatedMessage);
} else {
next(...arguments);
}
});

/**
Display a deprecation warning with the provided message and a stack trace
(Chrome and Firefox only). Ember build tools will remove any calls to
`Ember.deprecate()` when doing a production build.

@method deprecate
@param {String} message A description of the deprecation.
@param {Boolean|Function} test An optional boolean. If falsy, the deprecation
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, 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
*/
export default function() {
invoke('deprecate', ...arguments);
}
26 changes: 0 additions & 26 deletions packages/ember-debug/lib/deprecation-manager.js

This file was deleted.

27 changes: 27 additions & 0 deletions packages/ember-debug/lib/handlers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import isPlainFunction from 'ember-debug/is-plain-function';

export let HANDLERS = { };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you need to evict these somehow in tests, otherwise you will retain deprecations across app and isolated container instances.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean, these are global and are not changed per application or container.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah never mind I thought for a second this was going to hold a map of arrays. This is clearly not the case https://github.com/emberjs/ember.js/pull/11833/files#diff-889b83df6e6038c39617a4a40aec777fR12.


function normalizeTest(test) {
return isPlainFunction(test) ? test() : test;
}

export function registerHandler(type, callback) {
let nextHandler = HANDLERS[type] || function() { };

HANDLERS[type] = function(message, options) {
callback(message, options, nextHandler);
};
}

export function invoke(type, message, test, options) {
if (normalizeTest(test)) { return; }

let handlerForType = HANDLERS[type];

if (!handlerForType) { return; }

if (handlerForType) {
handlerForType(message, options);
}
}
3 changes: 3 additions & 0 deletions packages/ember-debug/lib/is-plain-function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function isPlainFunction(test) {
return typeof test === 'function' && test.PrototypeMixin === undefined;
}
125 changes: 14 additions & 111 deletions packages/ember-debug/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import { registerDebugFunction } from 'ember-metal/assert';
import isEnabled, { FEATURES } from 'ember-metal/features';
import EmberError from 'ember-metal/error';
import Logger from 'ember-metal/logger';
import deprecationManager, { deprecationLevels } from 'ember-debug/deprecation-manager';

import environment from 'ember-metal/environment';
import deprecate, {
registerHandler as registerDeprecationHandler
} from 'ember-debug/deprecate';
import warn, {
registerHandler as registerWarnHandler
} from 'ember-debug/warn';
import isPlainFunction from 'ember-debug/is-plain-function';

Ember.deprecate = deprecate;

/**
@module ember
Expand All @@ -19,9 +26,6 @@ import environment from 'ember-metal/environment';
@public
*/

function isPlainFunction(test) {
return typeof test === 'function' && test.PrototypeMixin === undefined;
}

/**
Define an assertion that will throw an exception if the condition is not
Expand Down Expand Up @@ -58,26 +62,6 @@ function assert(desc, test) {
}
}


/**
Display a warning with the provided message. Ember build tools will
remove any calls to `Ember.warn()` when doing a production build.

@method warn
@param {String} message A warning to display.
@param {Boolean} test An optional boolean. If falsy, the warning
will be displayed.
@public
*/
function warn(message, test) {
if (!test) {
Logger.warn('WARNING: ' + message);
if ('trace' in Logger) {
Logger.trace();
}
}
}

/**
Display a debug notice. Ember build tools will remove any calls to
`Ember.debug()` when doing a production build.
Expand All @@ -94,86 +78,6 @@ function debug(message) {
Logger.debug('DEBUG: ' + message);
}

/**
Display a deprecation warning with the provided message and a stack trace
(Chrome and Firefox only). Ember build tools will remove any calls to
`Ember.deprecate()` when doing a production build.

@method deprecate
@param {String} message A description of the deprecation.
@param {Boolean|Function} test An optional boolean. If falsy, the deprecation
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, 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
*/
function deprecate(message, test, options) {
if (Ember.ENV.RAISE_ON_DEPRECATION) {
deprecationManager.setDefaultLevel(deprecationLevels.RAISE);
}
if (deprecationManager.getLevel(options && options.id) === deprecationLevels.SILENCE) {
return;
}

var noDeprecation;

if (isPlainFunction(test)) {
noDeprecation = test();
} else {
noDeprecation = test;
}

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);
}

var error;

// When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
try { __fail__.fail(); } catch (e) { error = e; }

if (arguments.length === 3) {
Ember.assert('options argument to Ember.deprecate should be an object', options && typeof options === 'object');
if (options.url) {
message += ' See ' + options.url + ' for more details.';
}
}

if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) {
var stack;
var stackStr = '';

if (error['arguments']) {
// Chrome
stack = error.stack.replace(/^\s+at\s+/gm, '').
replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
stack.shift();
} else {
// Firefox
stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
replace(/^\(/gm, '{anonymous}(').split('\n');
}

stackStr = '\n ' + stack.slice(2).join('\n ');
message = message + stackStr;
}

Logger.warn('DEPRECATION: ' + message);
}



/**
Alias an old, deprecated method with its new counterpart.

Expand Down Expand Up @@ -297,13 +201,12 @@ if (!Ember.testing) {
}
}

Ember.Debug = {
_addDeprecationLevel(id, level) {
deprecationManager.setLevel(id, level);
},
_deprecationLevels: deprecationLevels
};
Ember.Debug = { };

if (isEnabled('ember-debug-handlers')) {
Ember.Debug.registerDeprecationHandler = registerDeprecationHandler;
Ember.Debug.registerWarnHandler = registerWarnHandler;
}
/*
We are transitioning away from `ember.js` to `ember.debug.js` to make
it much clearer that it is only for local development purposes.
Expand Down
27 changes: 27 additions & 0 deletions packages/ember-debug/lib/warn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Logger from 'ember-metal/logger';
import { registerHandler as genericRegisterHandler, invoke } from 'ember-debug/handlers';

export function registerHandler(handler) {
genericRegisterHandler('warn', handler);
}

registerHandler(function logWarning(message, options) {
Logger.warn('WARNING: ' + message);
if ('trace' in Logger) {
Logger.trace();
}
});

/**
Display a warning with the provided message. Ember build tools will
remove any calls to `Ember.warn()` when doing a production build.

@method warn
@param {String} message A warning to display.
@param {Boolean} test An optional boolean. If falsy, the warning
will be displayed.
@public
*/
export default function warn() {
invoke('warn', ...arguments);
}
Loading