Skip to content

Commit

Permalink
[FEATURE ember-debug-handlers]
Browse files Browse the repository at this point in the history
  • Loading branch information
rwjblue committed Jul 21, 2015
1 parent e12bb2f commit 649cb68
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 167 deletions.
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 = { };

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

0 comments on commit 649cb68

Please sign in to comment.