ember-inspector-prebuilt
Version:
A pre-built set of distributable assets from the ember.js ember-inspector project.
1,652 lines (1,441 loc) • 275 kB
JavaScript
(function(adapter, env) {
var define = window.define, requireModule = window.requireModule;
if (typeof define !== 'function' || typeof requireModule !== 'function') {
(function() {
var registry = {}, seen = {};
define = function(name, deps, callback) {
if (arguments.length < 3) {
callback = deps;
deps = [];
}
registry[name] = { deps: deps, callback: callback };
};
requireModule = function(name) {
if (seen[name]) { return seen[name]; }
seen[name] = {};
var mod = registry[name];
if (!mod) {
throw new Error("Module: '" + name + "' not found.");
}
var deps = mod.deps;
var callback = mod.callback;
var reified = [];
var exports;
for (var i = 0, l = deps.length; i < l; i++) {
if (deps[i] === 'exports') {
reified.push(exports = {});
} else {
reified.push(requireModule(deps[i]));
}
}
var value = callback.apply(this, reified);
seen[name] = exports || value;
return seen[name];
};
define.registry = registry;
define.seen = seen;
})();
}
define('ember-debug/adapters/basic', ['exports'], function (exports) {
/* globals requireModule */
/* eslint no-console: 0 */
'use strict';
var Ember = window.Ember;
var $ = Ember.$;
var A = Ember.A;
var computed = Ember.computed;
var RSVP = Ember.RSVP;
var EmberObject = Ember.Object;
var Promise = RSVP.Promise;
var resolve = RSVP.resolve;
exports['default'] = EmberObject.extend({
init: function init() {
var _this = this;
resolve(this.connect(), 'ember-inspector').then(function () {
_this.onConnectionReady();
}, null, 'ember-inspector');
},
/**
* Uses the current build's config module to determine
* the environment.
*
* @property environment
* @type {String}
*/
environment: computed(function () {
return requireModule('ember-debug/config')['default'].environment;
}),
debug: function debug() {
return console.debug.apply(console, arguments);
},
log: function log() {
return console.log.apply(console, arguments);
},
/**
* A wrapper for `console.warn`.
*
* @method warn
*/
warn: function warn() {
return console.warn.apply(console, arguments);
},
/**
Used to send messages to EmberExtension
@param {Object} type the message to the send
*/
sendMessage: function sendMessage() /* options */{},
/**
Register functions to be called
when a message from EmberExtension is received
@param {Function} callback
*/
onMessageReceived: function onMessageReceived(callback) {
this.get('_messageCallbacks').pushObject(callback);
},
/**
Inspect a specific element. This usually
means using the current environment's tools
to inspect the element in the DOM.
For example, in chrome, `inspect(elem)`
will open the Elements tab in dev tools
and highlight the element.
@param {DOM Element} elem
*/
inspectElement: function inspectElement() /* elem */{},
_messageCallbacks: computed(function () {
return A();
}),
_messageReceived: function _messageReceived(message) {
this.get('_messageCallbacks').forEach(function (callback) {
callback(message);
});
},
/**
* Handle an error caused by EmberDebug.
*
* This function rethrows in development and test envs,
* but warns instead in production.
*
* The idea is to control errors triggered by the inspector
* and make sure that users don't get mislead by inspector-caused
* bugs.
*
* @method handleError
* @param {Error} error
*/
handleError: function handleError(error) {
if (this.get('environment') === 'production') {
if (error && error instanceof Error) {
error = 'Error message: ' + error.message + '\nStack trace: ' + error.stack;
}
this.warn('Ember Inspector has errored.\n' + 'This is likely a bug in the inspector itself.\n' + ('You can report bugs at https://github.com/emberjs/ember-inspector.\n' + error));
} else {
this.warn('EmberDebug has errored:');
throw error;
}
},
/**
A promise that resolves when the connection
with the inspector is set up and ready.
@return {Promise}
*/
connect: function connect() {
var _this2 = this;
return new Promise(function (resolve, reject) {
$(function () {
if (_this2.isDestroyed) {
reject();
}
_this2.interval = setInterval(function () {
if (document.documentElement.dataset.emberExtension) {
clearInterval(_this2.interval);
resolve();
}
}, 10);
});
}, 'ember-inspector');
},
willDestroy: function willDestroy() {
this._super();
clearInterval(this.interval);
},
_isReady: false,
_pendingMessages: computed(function () {
return A();
}),
send: function send(options) {
if (this._isReady) {
this.sendMessage.apply(this, arguments);
} else {
this.get('_pendingMessages').push(options);
}
},
/**
Called when the connection is set up.
Flushes the pending messages.
*/
onConnectionReady: function onConnectionReady() {
var _this3 = this;
// Flush pending messages
var messages = this.get('_pendingMessages');
messages.forEach(function (options) {
return _this3.sendMessage(options);
});
messages.clear();
this._isReady = true;
}
});
});
define('ember-debug/adapters/bookmarklet', ['exports', 'ember-debug/adapters/basic'], function (exports, _emberDebugAdaptersBasic) {
'use strict';
var Ember = window.Ember;
var $ = Ember.$;
exports['default'] = _emberDebugAdaptersBasic['default'].extend({
init: function init() {
this._super();
this._listen();
},
sendMessage: function sendMessage(options) {
options = options || {};
window.emberInspector.w.postMessage(options, window.emberInspector.url);
},
_listen: function _listen() {
var _this = this;
window.addEventListener('message', function (e) {
if (e.origin !== window.emberInspector.url) {
return;
}
var message = e.data;
if (message.from === 'devtools') {
_this._messageReceived(message);
}
});
$(window).on('unload', function () {
_this.sendMessage({
unloading: true
});
});
}
});
});
define('ember-debug/adapters/chrome', ['exports', 'ember-debug/adapters/basic'], function (exports, _emberDebugAdaptersBasic) {
'use strict';
var Ember = window.Ember;
var computed = Ember.computed;
var run = Ember.run;
var extend = Ember.$.extend;
var isArray = Array.isArray;
var keys = Object.keys;
exports['default'] = _emberDebugAdaptersBasic['default'].extend({
connect: function connect() {
var _this = this;
var channel = this.get('_channel');
return this._super.apply(this, arguments).then(function () {
window.postMessage('debugger-client', '*', [channel.port2]);
_this._listen();
}, null, 'ember-inspector');
},
sendMessage: function sendMessage(options) {
options = options || {};
// If prototype extensions are disabled, `Ember.A()` arrays
// would not be considered native arrays, so it's not possible to
// "clone" them through postMessage unless they are converted to a
// native array.
if (!Ember.EXTEND_PROTOTYPES || Ember.EXTEND_PROTOTYPES.Array === false) {
options = deepCloneArrays(extend(true, {}, options));
}
this.get('_chromePort').postMessage(options);
},
/**
* Open the devtools "Elements" and select an element.
*
* NOTE:
* This method was supposed to call `inspect` which is a Chrome specific function
* that can either be called from the console or from code evaled using `inspectedWindow.eval`
* (which is how this code is executed). See https://developer.chrome.com/extensions/devtools#evaluating-js.
* However for some reason Chrome 52+ has started throwing an Error that `inspect`
* is not a function when called from this code. The current workaround is to
* message the Ember Ibspector asking it to execute `inspected.Window.eval('inspect(element)')`
* for us.
*
* @param {HTMLElement} elem The element to select
*/
inspectElement: function inspectElement(elem) {
/* inspect(elem); */
this.get('namespace.port').send('view:inspectDOMElement', {
elementSelector: '#' + elem.getAttribute('id')
});
},
_channel: computed(function () {
return new MessageChannel();
}).readOnly(),
_chromePort: computed(function () {
return this.get('_channel.port1');
}).readOnly(),
_listen: function _listen() {
var _this2 = this;
var chromePort = this.get('_chromePort');
chromePort.addEventListener('message', function (event) {
var message = event.data;
run(function () {
_this2._messageReceived(message);
});
});
chromePort.start();
}
});
/**
* Recursively clones all arrays. Needed because Chrome
* refuses to clone Ember Arrays when extend prototypes is disabled.
*
* If the item passed is an array, a clone of the array is returned.
* If the item is an object or an array, or array properties/items are cloned.
*
* @param {Mixed} item The item to clone
* @return {Mixed}
*/
function deepCloneArrays(item) {
if (isArray(item)) {
item = item.slice();
item.forEach(function (child, key) {
item[key] = deepCloneArrays(child);
});
} else if (item && typeof item === 'object') {
keys(item).forEach(function (key) {
item[key] = deepCloneArrays(item[key]);
});
}
return item;
}
});
define("ember-debug/adapters/firefox", ["exports", "ember-debug/adapters/basic"], function (exports, _emberDebugAdaptersBasic) {
/* eslint no-empty:0 */
"use strict";
var Ember = window.Ember;
var run = Ember.run;
exports["default"] = _emberDebugAdaptersBasic["default"].extend({
init: function init() {
this._super();
this._listen();
},
debug: function debug() {
// WORKAROUND: temporarily workaround issues with firebug console object:
// - https://github.com/tildeio/ember-extension/issues/94
// - https://github.com/firebug/firebug/pull/109
// - https://code.google.com/p/fbug/issues/detail?id=7045
try {
this._super.apply(this, arguments);
} catch (e) {}
},
log: function log() {
// WORKAROUND: temporarily workaround issues with firebug console object:
// - https://github.com/tildeio/ember-extension/issues/94
// - https://github.com/firebug/firebug/pull/109
// - https://code.google.com/p/fbug/issues/detail?id=7045
try {
this._super.apply(this, arguments);
} catch (e) {}
},
sendMessage: function sendMessage(options) {
options = options || {};
var event = document.createEvent("CustomEvent");
event.initCustomEvent("ember-debug-send", true, true, options);
document.documentElement.dispatchEvent(event);
},
inspectElement: function inspectElement(elem) {
this.sendMessage({
type: 'view:devtools:inspectDOMElement',
elementSelector: "#" + elem.getAttribute('id')
});
},
_listen: function _listen() {
var _this = this;
window.addEventListener('ember-debug-receive', function (event) {
var message = event.detail;
run(function () {
// FIX: needed to fix permission denied exception on Firefox >= 30
// - https://github.com/emberjs/ember-inspector/issues/147
// - https://blog.mozilla.org/addons/2014/04/10/changes-to-unsafewindow-for-the-add-on-sdk/
switch (typeof message) {
case "string":
message = JSON.parse(message);
break;
case "object":
break;
default:
throw new Error("ember-debug-receive: string or object expected");
}
_this._messageReceived(message);
});
});
}
});
});
define('ember-debug/adapters/websocket', ['exports', 'ember-debug/adapters/basic'], function (exports, _emberDebugAdaptersBasic) {
'use strict';
var Ember = window.Ember;
var $ = Ember.$;
var computed = Ember.computed;
var run = Ember.run;
var Promise = Ember.RSVP.Promise;
exports['default'] = _emberDebugAdaptersBasic['default'].extend({
sendMessage: function sendMessage(options) {
options = options || {};
this.get('socket').emit('emberInspectorMessage', options);
},
socket: computed(function () {
return window.EMBER_INSPECTOR_CONFIG.remoteDebugSocket;
}),
_listen: function _listen() {
var _this = this;
this.get('socket').on('emberInspectorMessage', function (message) {
run(function () {
_this._messageReceived(message);
});
});
},
_disconnect: function _disconnect() {
this.get('socket').removeAllListeners("emberInspectorMessage");
},
connect: function connect() {
var _this2 = this;
return new Promise(function (resolve, reject) {
$(function () {
if (_this2.isDestroyed) {
reject();
}
var EMBER_INSPECTOR_CONFIG = window.EMBER_INSPECTOR_CONFIG;
if (typeof EMBER_INSPECTOR_CONFIG === 'object' && EMBER_INSPECTOR_CONFIG.remoteDebugSocket) {
resolve();
}
});
}).then(function () {
_this2._listen();
});
},
willDestroy: function willDestroy() {
this._disconnect();
}
});
});
define('ember-debug/addons/ember-new-computed/index', ['exports', 'ember-debug/addons/ember-new-computed/utils/can-use-new-syntax'], function (exports, _emberDebugAddonsEmberNewComputedUtilsCanUseNewSyntax) {
'use strict';
var Ember = window.Ember;
var computed = Ember.computed;
exports['default'] = function () {
var polyfillArguments = [];
var config = arguments[arguments.length - 1];
if (typeof config === 'function' || _emberDebugAddonsEmberNewComputedUtilsCanUseNewSyntax['default']) {
return computed.apply(this, arguments);
}
for (var i = 0, l = arguments.length - 1; i < l; i++) {
polyfillArguments.push(arguments[i]);
}
var func = undefined;
if (config.set) {
func = function (key, value) {
if (arguments.length > 1) {
return config.set.call(this, key, value);
} else {
return config.get.call(this, key);
}
};
} else {
func = function (key) {
return config.get.call(this, key);
};
}
polyfillArguments.push(func);
return computed.apply(this, polyfillArguments);
};
});
define("ember-debug/addons/ember-new-computed/utils/can-use-new-syntax", ["exports"], function (exports) {
"use strict";
var Ember = window.Ember;
var computed = Ember.computed;
var supportsSetterGetter = undefined;
try {
computed({
set: function set() {},
get: function get() {}
});
supportsSetterGetter = true;
} catch (e) {
supportsSetterGetter = false;
}
exports["default"] = supportsSetterGetter;
});
define('ember-debug/container-debug', ['exports', 'ember-debug/mixins/port-mixin'], function (exports, _emberDebugMixinsPortMixin) {
'use strict';
var Ember = window.Ember;
var EmberObject = Ember.Object;
var computed = Ember.computed;
var oneWay = computed.oneWay;
exports['default'] = EmberObject.extend(_emberDebugMixinsPortMixin['default'], {
namespace: null,
port: oneWay('namespace.port').readOnly(),
application: oneWay('namespace.application').readOnly(),
objectInspector: oneWay('namespace.objectInspector').readOnly(),
container: computed('application', function () {
return this.get('application.__container__');
}),
portNamespace: 'container',
TYPES_TO_SKIP: computed(function () {
return ['component-lookup', 'container-debug-adapter', 'resolver-for-debugging', 'event_dispatcher'];
}),
typeFromKey: function typeFromKey(key) {
return key.split(':').shift();
},
nameFromKey: function nameFromKey(key) {
return key.split(':').pop();
},
shouldHide: function shouldHide(type) {
return type[0] === '-' || this.get('TYPES_TO_SKIP').indexOf(type) !== -1;
},
instancesByType: function instancesByType() {
var key = undefined;
var instancesByType = {};
var cache = this.get('container').cache;
// Detect if InheritingDict (from Ember < 1.8)
if (typeof cache.dict !== 'undefined' && typeof cache.eachLocal !== 'undefined') {
cache = cache.dict;
}
for (key in cache) {
var type = this.typeFromKey(key);
if (this.shouldHide(type)) {
continue;
}
if (instancesByType[type] === undefined) {
instancesByType[type] = [];
}
instancesByType[type].push({
fullName: key,
instance: cache[key]
});
}
return instancesByType;
},
getTypes: function getTypes() {
var key = undefined;
var types = [];
var instancesByType = this.instancesByType();
for (key in instancesByType) {
types.push({ name: key, count: instancesByType[key].length });
}
return types;
},
getInstances: function getInstances(type) {
var _this = this;
var instances = this.instancesByType()[type];
if (!instances) {
return null;
}
return instances.map(function (item) {
return {
name: _this.nameFromKey(item.fullName),
fullName: item.fullName,
inspectable: _this.get('objectInspector').canSend(item.instance)
};
});
},
messages: {
getTypes: function getTypes() {
this.sendMessage('types', {
types: this.getTypes()
});
},
getInstances: function getInstances(message) {
var instances = this.getInstances(message.containerType);
if (instances) {
this.sendMessage('instances', {
instances: instances,
status: 200
});
} else {
this.sendMessage('instances', {
status: 404
});
}
},
sendInstanceToConsole: function sendInstanceToConsole(message) {
var instance = this.get('container').lookup(message.name);
this.get('objectToConsole').sendValueToConsole(instance);
}
}
});
});
define('ember-debug/data-debug', ['exports', 'ember-debug/mixins/port-mixin'], function (exports, _emberDebugMixinsPortMixin) {
'use strict';
var Ember = window.Ember;
var EmberObject = Ember.Object;
var computed = Ember.computed;
var guidFor = Ember.guidFor;
var A = Ember.A;
var alias = computed.alias;
exports['default'] = EmberObject.extend(_emberDebugMixinsPortMixin['default'], {
init: function init() {
this._super();
this.sentTypes = {};
this.sentRecords = {};
},
sentTypes: {},
sentRecords: {},
releaseTypesMethod: null,
releaseRecordsMethod: null,
adapter: computed('application', function () {
var container = this.get('application').__container__;
// dataAdapter:main is deprecated
var adapter = this._resolve('data-adapter:main') && container.lookup('data-adapter:main');
// column limit is now supported at the inspector level
adapter.set('attributeLimit', 100);
return adapter;
}),
_resolve: function _resolve(name) {
// Ember >= 2.1
if (this.get('application').resolveRegistration) {
return this.get('application').resolveRegistration(name);
}
var container = this.get('application').__container__;
var registry = this.get('application.registry');
if (registry) {
// Ember >= 1.11
return registry.resolve(name);
} else if (container.resolve) {
// Ember < 1.11
return container.resolve(name);
} else {
// Ember >= 2.0 < 2.1
return container.registry.resolve(name);
}
},
namespace: null,
port: alias('namespace.port'),
application: alias('namespace.application'),
objectInspector: alias('namespace.objectInspector'),
portNamespace: 'data',
modelTypesAdded: function modelTypesAdded(types) {
var _this = this;
var typesToSend = undefined;
typesToSend = types.map(function (type) {
return _this.wrapType(type);
});
this.sendMessage('modelTypesAdded', {
modelTypes: typesToSend
});
},
modelTypesUpdated: function modelTypesUpdated(types) {
var _this2 = this;
var typesToSend = types.map(function (type) {
return _this2.wrapType(type);
});
this.sendMessage('modelTypesUpdated', {
modelTypes: typesToSend
});
},
wrapType: function wrapType(type) {
var objectId = guidFor(type.object);
this.sentTypes[objectId] = type;
return {
columns: type.columns,
count: type.count,
name: type.name,
objectId: objectId
};
},
recordsAdded: function recordsAdded(recordsReceived) {
var _this3 = this;
var records = recordsReceived.map(function (record) {
return _this3.wrapRecord(record);
});
this.sendMessage('recordsAdded', { records: records });
},
recordsUpdated: function recordsUpdated(recordsReceived) {
var _this4 = this;
var records = recordsReceived.map(function (record) {
return _this4.wrapRecord(record);
});
this.sendMessage('recordsUpdated', { records: records });
},
recordsRemoved: function recordsRemoved(index, count) {
this.sendMessage('recordsRemoved', { index: index, count: count });
},
wrapRecord: function wrapRecord(record) {
var objectId = guidFor(record.object);
var columnValues = {};
var searchKeywords = [];
this.sentRecords[objectId] = record;
// make objects clonable
for (var i in record.columnValues) {
columnValues[i] = this.get('objectInspector').inspect(record.columnValues[i]);
}
// make sure keywords can be searched and clonable
searchKeywords = A(record.searchKeywords).filter(function (keyword) {
return typeof keyword === 'string' || typeof keyword === 'number';
});
return {
columnValues: columnValues,
searchKeywords: searchKeywords,
filterValues: record.filterValues,
color: record.color,
objectId: objectId
};
},
releaseTypes: function releaseTypes() {
if (this.releaseTypesMethod) {
this.releaseTypesMethod();
this.releaseTypesMethod = null;
this.sentTypes = {};
}
},
releaseRecords: function releaseRecords() {
if (this.releaseRecordsMethod) {
this.releaseRecordsMethod();
this.releaseRecordsMethod = null;
this.sentRecords = {};
}
},
willDestroy: function willDestroy() {
this._super();
this.releaseRecords();
this.releaseTypes();
},
messages: {
checkAdapter: function checkAdapter() {
this.sendMessage('hasAdapter', { hasAdapter: !!this.get('adapter') });
},
getModelTypes: function getModelTypes() {
var _this5 = this;
this.releaseTypes();
this.releaseTypesMethod = this.get('adapter').watchModelTypes(function (types) {
_this5.modelTypesAdded(types);
}, function (types) {
_this5.modelTypesUpdated(types);
});
},
releaseModelTypes: function releaseModelTypes() {
this.releaseTypes();
},
getRecords: function getRecords(message) {
var _this6 = this,
_arguments = arguments;
var type = this.sentTypes[message.objectId];
this.releaseRecords();
var typeOrName = undefined;
if (this.get('adapter.acceptsModelName')) {
// Ember >= 1.3
typeOrName = type.name;
} else {
// support for legacy Ember < 1.3
typeOrName = type.object;
}
var releaseMethod = this.get('adapter').watchRecords(typeOrName, function (recordsReceived) {
_this6.recordsAdded(recordsReceived);
}, function (recordsUpdated) {
_this6.recordsUpdated(recordsUpdated);
}, function () {
_this6.recordsRemoved.apply(_this6, _arguments);
});
this.releaseRecordsMethod = releaseMethod;
},
releaseRecords: function releaseRecords() {
this.releaseRecords();
},
inspectModel: function inspectModel(message) {
this.get('objectInspector').sendObject(this.sentRecords[message.objectId].object);
},
getFilters: function getFilters() {
this.sendMessage('filters', {
filters: this.get('adapter').getFilters()
});
}
}
});
});
define("ember-debug/deprecation-debug", ["exports", "ember-debug/mixins/port-mixin", "ember-debug/libs/source-map"], function (exports, _emberDebugMixinsPortMixin, _emberDebugLibsSourceMap) {
"use strict";
var Ember = window.Ember;
var EmberObject = Ember.Object;
var computed = Ember.computed;
var guidFor = Ember.guidFor;
var run = Ember.run;
var RSVP = Ember.RSVP;
var A = Ember.A;
var resolve = RSVP.resolve;
var all = RSVP.all;
var oneWay = computed.oneWay;
exports["default"] = EmberObject.extend(_emberDebugMixinsPortMixin["default"], {
portNamespace: 'deprecation',
port: oneWay('namespace.port').readOnly(),
adapter: oneWay('port.adapter').readOnly(),
deprecations: computed(function () {
return A();
}),
groupedDeprecations: computed(function () {
return {};
}),
deprecationsToSend: computed(function () {
return A();
}),
sourceMap: computed(function () {
return _emberDebugLibsSourceMap["default"].create();
}),
emberCliConfig: oneWay('namespace.generalDebug.emberCliConfig').readOnly(),
init: function init() {
this._super();
this.replaceDeprecate();
},
/**
* Checks if ember-cli and looks for source maps.
*/
fetchSourceMap: function fetchSourceMap(stackStr) {
var _this = this;
if (this.get('emberCliConfig') && this.get('emberCliConfig.environment') === 'development') {
return this.get('sourceMap').map(stackStr).then(function (mapped) {
if (mapped && mapped.length > 0) {
var source = mapped.find(function (item) {
return item.source && !!item.source.match(new RegExp(_this.get('emberCliConfig.modulePrefix')));
});
if (source) {
source.found = true;
} else {
source = mapped.get('firstObject');
source.found = false;
}
return source;
}
}, null, 'ember-inspector');
} else {
return resolve(null, 'ember-inspector');
}
},
sendPending: function sendPending() {
var _this2 = this;
var deprecations = A();
var promises = all(this.get('deprecationsToSend').map(function (deprecation) {
var obj = undefined;
var promise = resolve(undefined, 'ember-inspector');
var grouped = _this2.get('groupedDeprecations');
_this2.get('deprecations').pushObject(deprecation);
var id = guidFor(deprecation.message);
obj = grouped[id];
if (obj) {
obj.count++;
obj.url = obj.url || deprecation.url;
} else {
obj = deprecation;
obj.count = 1;
obj.id = id;
obj.sources = A();
grouped[id] = obj;
}
var found = obj.sources.findBy('stackStr', deprecation.stackStr);
if (!found) {
(function () {
var stackStr = deprecation.stackStr;
promise = _this2.fetchSourceMap(stackStr).then(function (map) {
obj.sources.pushObject({ map: map, stackStr: stackStr });
if (map) {
obj.hasSourceMap = true;
}
}, null, 'ember-inspector');
})();
}
return promise.then(function () {
delete obj.stackStr;
deprecations.addObject(obj);
}, null, 'ember-inspector');
}));
promises.then(function () {
_this2.sendMessage('deprecationsAdded', { deprecations: deprecations });
_this2.get('deprecationsToSend').clear();
_this2.sendCount();
}, null, 'ember-inspector');
},
sendCount: function sendCount() {
this.sendMessage('count', {
count: this.get('deprecations.length') + this.get('deprecationsToSend.length')
});
},
messages: {
watch: function watch() {
this._watching = true;
var grouped = this.get('groupedDeprecations');
var deprecations = [];
for (var i in grouped) {
if (!grouped.hasOwnProperty(i)) {
continue;
}
deprecations.push(grouped[i]);
}
this.sendMessage('deprecationsAdded', {
deprecations: deprecations
});
this.sendPending();
},
sendStackTraces: function sendStackTraces(message) {
var _this3 = this;
var deprecation = message.deprecation;
deprecation.sources.forEach(function (source) {
var stack = source.stackStr;
stack = stack.split('\n');
stack.unshift("Ember Inspector (Deprecation Trace): " + (deprecation.message || ''));
_this3.get('adapter').log(stack.join('\n'));
});
},
getCount: function getCount() {
this.sendCount();
},
clear: function clear() {
run.cancel(this.debounce);
this.get('deprecations').clear();
this.set('groupedDeprecations', {});
this.sendCount();
},
release: function release() {
this._watching = false;
}
},
willDestroy: function willDestroy() {
Ember.deprecate = this.originalDeprecate;
this.originalDeprecate = null;
run.cancel(this.debounce);
return this._super.apply(this, arguments);
},
replaceDeprecate: function replaceDeprecate() {
var self = this;
this.originalDeprecate = Ember.deprecate;
Ember.deprecate = function (message, test, options) {
/* global __fail__*/
// Code taken from https://github.com/emberjs/ember.js/blob/master/packages/ember-debug/lib/main.js
var noDeprecation = undefined;
if (typeof test === 'function' && !EmberObject.detect(test)) {
// try/catch to support old Ember versions
try {
noDeprecation = test();
} catch (e) {
noDeprecation = true;
}
} else {
noDeprecation = test;
}
if (noDeprecation) {
return;
}
var error = undefined;
// When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
try {
__fail__.fail();
} catch (e) {
error = e;
}
var stack = undefined;
var stackStr = '';
if (error.stack) {
// var 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 ");
}
var url = undefined;
if (arguments.length === 3 && options && typeof options === 'object') {
url = options.url;
}
var deprecation = { message: message, stackStr: stackStr, url: url };
// For ember-debug testing we usually don't want
// to catch deprecations
if (!self.get('namespace').IGNORE_DEPRECATIONS) {
self.get('deprecationsToSend').pushObject(deprecation);
run.cancel(self.debounce);
if (self._watching) {
self.debounce = run.debounce(self, 'sendPending', 100);
} else {
self.debounce = run.debounce(self, 'sendCount', 100);
}
if (!self._warned) {
self.get("adapter").warn("Deprecations were detected, see the Ember Inspector deprecations tab for more details.");
self._warned = true;
}
}
};
}
});
});
define('ember-debug/general-debug', ['exports', 'ember-debug/mixins/port-mixin'], function (exports, _emberDebugMixinsPortMixin) {
/* eslint no-empty:0 */
'use strict';
var Ember = window.Ember;
var $ = Ember.$;
var computed = Ember.computed;
var EmberObject = Ember.Object;
var A = Ember.A;
var libraries = Ember.libraries;
var oneWay = computed.oneWay;
var GeneralDebug = EmberObject.extend(_emberDebugMixinsPortMixin['default'], {
namespace: null,
port: oneWay('namespace.port').readOnly(),
application: oneWay('namespace.application').readOnly(),
promiseDebug: oneWay('namespace.promiseDebug').readOnly(),
portNamespace: 'general',
// Keep an eye on https://github.com/ember-cli/ember-cli/issues/3045
emberCliConfig: computed(function () {
var config = undefined;
$('meta[name]').each(function () {
var meta = $(this);
var match = meta.attr('name').match(/environment$/);
if (match) {
try {
/* global unescape */
config = JSON.parse(unescape(meta.attr('content')));
return false;
} catch (e) {}
}
});
return config;
}),
sendBooted: function sendBooted() {
this.sendMessage('applicationBooted', {
booted: this.get('application.__inspector__booted')
});
},
sendReset: function sendReset() {
this.sendMessage('reset', {
reset: true
});
},
messages: {
applicationBooted: function applicationBooted() {
this.sendBooted();
},
getLibraries: function getLibraries() {
// Ember has changed where the array of libraries is located.
// In older versions, `Ember.libraries` was the array itself,
// but now it's found under _registry.
if (libraries._registry) {
libraries = libraries._registry;
}
this.sendMessage('libraries', { libraries: arrayize(libraries) });
},
refresh: function refresh() {
window.location.reload();
}
}
});
function arrayize(enumerable) {
return A(enumerable).map(function (item) {
return item;
});
}
exports['default'] = GeneralDebug;
});
define('ember-debug/libs/glimmer-tree', ['exports', 'ember-debug/utils/name-functions'], function (exports, _emberDebugUtilsNameFunctions) {
/**
* This class contains functionality related to for Ember versions
* using Glimmer 2 (Ember >= 2.9):
*
* It has the following main responsibilities:
*
* - Building the view tree.
* - Highlighting components/outlets when the view tree is hovered.
* - Highlighting components/outlets when the views themselves are hovered.
* - Finding the model of a specific outlet/component.
*
* The view tree is a hierarchy of nodes (optionally) containing the following info:
* - name
* - template
* - id
* - view class
* - duration
* - tag name
* - model
* - controller
* - type
*
* Once the view tree is generated it can be sent to the Ember Inspector to be displayed.
*
* @class GlimmerTree
*/
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var Ember = window.Ember;
var EmberObject = Ember.Object;
var typeOf = Ember.typeOf;
var isNone = Ember.isNone;
var Controller = Ember.Controller;
var ViewUtils = Ember.ViewUtils;
var get = Ember.get;
var A = Ember.A;
var getRootViews = ViewUtils.getRootViews;
var getChildViews = ViewUtils.getChildViews;
var getViewBoundingClientRect = ViewUtils.getViewBoundingClientRect;
var _default = (function () {
/**
* Sets up the initial options.
*
* @method constructor
* @param {Object} options
* - {Container} container The Ember app's container.
* - {Function} retainObject Called to retain an object for future inspection.
* - {Object} options Options whether to show components or not.
* - {Object} durations Hash containing time to render per view id.
* - {Function} highlightRange Called to highlight a range of elements.
* - {Object} ObjectInspector Used to inspect models.
* - {Object} viewRegistry Hash containing all currently rendered components by id.
*/
function _default(_ref) {
var container = _ref.container;
var retainObject = _ref.retainObject;
var options = _ref.options;
var durations = _ref.durations;
var highlightRange = _ref.highlightRange;
var objectInspector = _ref.objectInspector;
var viewRegistry = _ref.viewRegistry;
_classCallCheck(this, _default);
this.container = container;
this.retainObject = retainObject;
this.options = options;
this.durations = durations;
this.highlightRange = highlightRange;
this.objectInspector = objectInspector;
this.viewRegistry = viewRegistry;
}
/**
* @method updateOptions
* @param {Object} options
*/
_createClass(_default, [{
key: 'updateOptions',
value: function updateOptions(options) {
this.options = options;
}
/**
* @method updateDurations
* @param {Object} durations
*/
}, {
key: 'updateDurations',
value: function updateDurations(durations) {
this.duations = durations;
}
/**
* Builds the view tree. The view tree may or may not contain
* components depending on the current options.
*
* The view tree has the top level outlet as the root of the tree.
* The format is:
* {
* value: |hash of properties|,
* children: [
* {
* value: |hash of properties|,
* children: []
* },
* {
* value: |hash of properties|,
* children: [...]
* }]
* }
*
* We are building the tree is by doing the following steps:
* - Build the outlet tree by walking the outlet state.
* - Build several component trees, each tree belonging to one controller.
* - Assign each controller-specific component tree as a child of the outlet corresponding
* to that specific controller.
*
* @method build
* @return {Object} The view tree
*/
}, {
key: 'build',
value: function build() {
if (this.getRoot()) {
var outletTree = this.buildOutletTree();
var componentTrees = this.options.components ? this.buildComponentTrees(outletTree) : [];
return this.addComponentsToOutlets(outletTree, componentTrees);
}
}
/**
* Starts with the root and walks the tree till
* the leaf outlets. The format is:
* {
* value: |inspected outlet|,
* children:
* [
* {
* value: |inspected outlet|,
* children: [...]
* }
* ]
* }
*
* @method buildOutletTree
* @return {Object} Tree of inspected outlets
*/
}, {
key: 'buildOutletTree',
value: function buildOutletTree() {
var outletTree = this.makeOutletTree(this.getApplicationOutlet());
// set root element's id
var rootElement = this.elementForRoot();
outletTree.value.elementId = rootElement.getAttribute('id');
outletTree.value.tagName = 'div';
return outletTree;
}
/**
* The recursive part of building the outlet tree.
*
* Return format:
* {
* value: |inspected outlet|
* controller: |controller instance|
* children: [...]
* }
*
* @method makeOutletTree
* @param {Object} outletState
* @return {Object} The inspected outlet tree
*/
}, {
key: 'makeOutletTree',
value: function makeOutletTree(outletState) {
var controller = outletState.render.controller;
var outlets = outletState.outlets;
var node = { value: this.inspectOutlet(outletState), controller: controller, children: [] };
for (var key in outlets) {
node.children.push(this.makeOutletTree(outlets[key]));
}
return node;
}
/**
* Builds the component trees. Each tree corresponds to one controller.
* A component's controller is determined by its target (or ancestor's target).
*
* Has the following format:
* {
* controller: |The controller instance|,
* components: [|component tree|]
* }
*
* @method buildComponentTrees
* @param {Object} outletTree
* @return {Array} The component tree
*/
}, {
key: 'buildComponentTrees',
value: function buildComponentTrees(outletTree) {
var _this = this;
var controllers = this.controllersFromOutletTree(outletTree);
return controllers.map(function (controller) {
var components = _this.componentsForController(_this.topComponents(), controller);
return { controller: controller, components: components };
});
}
/**
* Builds a tree of components that have a specific controller
* as their target. If a component does not match the given
* controller, we ignore it and move on to its children.
*
* Format:
* [
* {
* value: |inspected component|,
* children: [...]
* },
* {
* value: |inspected component|
* children: [{
* value: |inspected component|
* children: [...]
* }]
* }
* ]
*
* @method componentsForController
* @param {Array} components Subtree of components
* @param {Controller} controller
* @return {Array} Array of inspected components
*/
}, {
key: 'componentsForController',
value: function componentsForController(components, controller) {
var _this2 = this;
var arr = [];
components.forEach(function (component) {
var currentController = _this2.controllerForComponent(component);
if (!currentController) {
return;
}
var children = _this2.componentsForController(_this2.childComponents(component), controller);
if (currentController === controller) {
arr.push({ value: _this2.inspectComponent(component), children: children });
} else {
arr = arr.concat(children);
}
});
return arr;
}
/**
* Given a component, return its children.
*
* @method childComponents
* @param {Component} component The parent component
* @return {Array} Array of components (children)
*/
}, {
key: 'childComponents',
value: function childComponents(component) {
return getChildViews(component);
}
/**
* Get the top level components.
*
* @method topComponents
* @return {Array} Array of components
*/
}, {
key: 'topComponents',
value: function topComponents() {
return getRootViews(this.container.owner);
}
/**
* Assign each component tree to it matching outlet
* by comparing controllers.
*
* Return format:
* {
* value: |inspected root outlet|
* children: [
* {
* value: |inspected outlet or component|
* chidren: [...]
* },
* {
* value: |inspected outlet or component|
* chidren: [...]
* }
* ]
* }
*
* @method addComponentsToOutlets
* @param {Object} outletTree
* @param {Object} componentTrees
*/
}, {
key: 'addComponentsToOutlets',
value: function addComponentsToOutlets(outletTree, componentTrees) {
var _this3 = this;
var value = outletTree.value;
var controller = outletTree.controller;
var children = outletTree.children;
children = children.map(function (child) {
return _this3.addComponentsToOutlets(child, componentTrees);
});
var _ref2 = A(componentTrees).findBy('controller', controller) || { components: [] };
var components = _ref2.components;
return { value: value, children: children.concat(components) };
}
/**
* @method controllersFromOutletTree
*
* @param {Controller} inspectedOutlet
* @return {Array} List of controllers
*/
}, {
key: 'controllersFromOutletTree',
value: function controllersFromOutletTree(_ref3) {
var _ref4;
var controller = _ref3.controller;
var children = _ref3.children;
return (_ref4 = [controller]).concat.apply(_ref4, _toConsumableArray(children.map(this.controllersFromOutletTree.bind(this))));
}
/**
* @method getRouter
* @return {Router}
*/
}, {
key: 'getRouter',
value: function getRouter() {
return this.container.lookup('router:main');
}
/**
* Returns the current top level view.
*
* @method getRoot
* @return {OutletView}
*/
}, {
key: 'getRoot',
value: function getRoot() {
return this.getRouter().get('_toplevelView');
}
/**
* Returns the application (top) outlet.
*
* @return {Object} The application outlet state
*/
}, {
key: 'getApplicationOutlet',
value: function getApplicationOutlet() {
return this.getRoot().outletState.outlets.main;
}
/**
* The root's DOM element. The root is the only outlet view
* with a DOM element.
*
* @method elementForRoot
* @return {Element}
*/
}, {
key: 'elementForRoot',
value: function elementForRoot() {
var renderer = this.container.lookup('renderer:-dom');
return renderer._roots && renderer._roots[0] && renderer._roots[0].result && renderer._roots[0].result.firstNode();
}
/**
* Returns a component's template name.
*
* @method templateForComponent
* @param {Component} component
* @return {String} The template name
*/
}, {
key: 'templateForComponent',
value: function templateForComponent(component) {
var template = component.get('layoutName');
if (!template) {
var layout = component.get('layout');
if (layout) {
layout = this.getGlimmerEnvironment().getTemplate(layout);
} else {
var componentName = component.get('_debugContainerKey');
if (componentName) {
var layoutName = componentName.replace(/component:/, 'template:components/');
layout = this.container.lookup(layoutName);
}
}
template = this.nameFromLayout(layout);
}
return template;
}
/**
* Inspects and outlet state. Extracts the name, controller, template,
* and model.
*
* @method inspectOutlet
* @param {Object} outlet The outlet state
* @return {Object} The inspected outlet
*/
}, {
key: 'inspectOutlet',
value: function inspectOutlet(outlet) {
var name = this.nameForOutlet(outlet);
var template = this.templateForOutlet(outlet);
var controller = this.controllerForOutlet(outlet);
va