Skip to content

Commit

Permalink
Merge pull request #15224 from rwjblue/fix-debug
Browse files Browse the repository at this point in the history
[BUGFIX beta] Refactor ember-debug to support better prod stripping.
  • Loading branch information
rwjblue authored May 11, 2017
2 parents 73d6f46 + 056ef6b commit 5a35da5
Show file tree
Hide file tree
Showing 7 changed files with 487 additions and 416 deletions.
265 changes: 140 additions & 125 deletions packages/ember-debug/lib/deprecate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*global __fail__*/
import { DEBUG } from 'ember-env-flags';

import EmberError from './error';
import Logger from 'ember-console';
Expand All @@ -7,6 +8,11 @@ import { ENV } from 'ember-environment';

import { registerHandler as genericRegisterHandler, invoke } from './handlers';

/**
@module ember
@submodule ember-debug
*/

/**
Allows for runtime registration of handler functions that override the default deprecation behavior.
Deprecations are invoked by calls to [Ember.deprecate](http://emberjs.com/api/classes/Ember.html#method_deprecate).
Expand Down Expand Up @@ -42,150 +48,159 @@ import { registerHandler as genericRegisterHandler, invoke } from './handlers';
@param handler {Function} A function to handle deprecation calls.
@since 2.1.0
*/
export function registerHandler(handler) {
genericRegisterHandler('deprecate', handler);
}
let registerHandler = () => {};
let missingOptionsDeprecation, missingOptionsIdDeprecation, missingOptionsUntilDeprecation, deprecate;

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.`;
if (DEBUG) {
registerHandler = function registerHandler(handler) {
genericRegisterHandler('deprecate', handler);
}

return message;
}

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

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

let captureErrorForStack;
if (options && options.url) {
message += ` See ${options.url} for more details.`;
}

if (new Error().stack) {
captureErrorForStack = () => new Error();
} else {
captureErrorForStack = () => {
try { __fail__.fail(); } catch (e) { return e; }
};
}
return message;
}

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

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');
}
registerHandler(function logDeprecationToConsole(message, options) {
let updatedMessage = formatMessage(message, options);

stackStr = `\n ${stack.slice(2).join('\n ')}`;
}
Logger.warn(`DEPRECATION: ${updatedMessage}`);
});

let updatedMessage = formatMessage(message, options);
let captureErrorForStack;

Logger.warn(`DEPRECATION: ${updatedMessage}${stackStr}`);
if (new Error().stack) {
captureErrorForStack = () => new Error();
} else {
next(...arguments);
captureErrorForStack = () => {
try { __fail__.fail(); } catch (e) { return e; }
};
}
});

registerHandler(function raiseOnDeprecation(message, options, next) {
if (ENV.RAISE_ON_DEPRECATION) {
let updatedMessage = formatMessage(message);
registerHandler(function logDeprecationStackTrace(message, options, next) {
if (ENV.LOG_STACKTRACE_ON_DEPRECATION) {
let stackStr = '';
let error = captureErrorForStack();
let stack;

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

throw new EmberError(updatedMessage);
} else {
next(...arguments);
}
});
Logger.warn(`DEPRECATION: ${updatedMessage}${stackStr}`);
} else {
next(...arguments);
}
});

export let missingOptionsDeprecation = 'When calling `Ember.deprecate` you ' +
'must provide an `options` hash as the third parameter. ' +
'`options` should include `id` and `until` properties.';
export let missingOptionsIdDeprecation = 'When calling `Ember.deprecate` you must provide `id` in options.';
export let missingOptionsUntilDeprecation = 'When calling `Ember.deprecate` you must provide `until` in options.';
registerHandler(function raiseOnDeprecation(message, options, next) {
if (ENV.RAISE_ON_DEPRECATION) {
let updatedMessage = formatMessage(message);

/**
@module ember
@submodule ember-debug
*/
throw new EmberError(updatedMessage);
} else {
next(...arguments);
}
});

/**
Display a deprecation warning with the provided message and a stack trace
(Chrome and Firefox only).
* In a production build, this method is defined as an empty function (NOP).
Uses of this method in Ember itself are stripped from the ember.prod.js build.
@method deprecate
@param {String} message A description of the deprecation.
@param {Boolean} test A boolean. If falsy, the deprecation will be displayed.
@param {Object} options
@param {String} options.id 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".
@param {string} options.until The version of Ember when this deprecation
warning will be removed.
@param {String} [options.url] An optional url to the transition guide on the
emberjs.com website.
@for Ember
@public
@since 1.0.0
*/
export default function deprecate(message, test, options) {
if (!options || (!options.id && !options.until)) {
deprecate(
missingOptionsDeprecation,
false,
{
id: 'ember-debug.deprecate-options-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
}
missingOptionsDeprecation = 'When calling `Ember.deprecate` you ' +
'must provide an `options` hash as the third parameter. ' +
'`options` should include `id` and `until` properties.';
missingOptionsIdDeprecation = 'When calling `Ember.deprecate` you must provide `id` in options.';
missingOptionsUntilDeprecation = 'When calling `Ember.deprecate` you must provide `until` in options.';

/**
Display a deprecation warning with the provided message and a stack trace
(Chrome and Firefox only).
* In a production build, this method is defined as an empty function (NOP).
Uses of this method in Ember itself are stripped from the ember.prod.js build.
@method deprecate
@param {String} message A description of the deprecation.
@param {Boolean} test A boolean. If falsy, the deprecation will be displayed.
@param {Object} options
@param {String} options.id 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".
@param {string} options.until The version of Ember when this deprecation
warning will be removed.
@param {String} [options.url] An optional url to the transition guide on the
emberjs.com website.
@for Ember
@public
@since 1.0.0
*/
deprecate = function deprecate(message, test, options) {
if (!options || (!options.id && !options.until)) {
deprecate(
missingOptionsDeprecation,
false,
{
id: 'ember-debug.deprecate-options-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
}

if (options && !options.id) {
deprecate(
missingOptionsIdDeprecation,
false,
{
id: 'ember-debug.deprecate-id-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
}
if (options && !options.id) {
deprecate(
missingOptionsIdDeprecation,
false,
{
id: 'ember-debug.deprecate-id-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
}

if (options && !options.until) {
deprecate(
missingOptionsUntilDeprecation,
options && options.until,
{
id: 'ember-debug.deprecate-until-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
if (options && !options.until) {
deprecate(
missingOptionsUntilDeprecation,
options && options.until,
{
id: 'ember-debug.deprecate-until-missing',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
}
);
}

invoke('deprecate', ...arguments);
}
}

export default deprecate;

invoke('deprecate', ...arguments);
export {
registerHandler,
missingOptionsDeprecation,
missingOptionsIdDeprecation,
missingOptionsUntilDeprecation
}
34 changes: 23 additions & 11 deletions packages/ember-debug/lib/handlers.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import { DEBUG } from 'ember-env-flags';

export let HANDLERS = { };

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

HANDLERS[type] = (message, options) => {
callback(message, options, nextHandler);
};
}
if (DEBUG) {
registerHandler = function registerHandler(type, callback) {
let nextHandler = HANDLERS[type] || (() => { });

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

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

let handlerForType = HANDLERS[type];
let handlerForType = HANDLERS[type];

if (handlerForType) {
handlerForType(message, options);
if (handlerForType) {
handlerForType(message, options);
}
}
}

export {
registerHandler,
invoke
}
Loading

0 comments on commit 5a35da5

Please sign in to comment.