electron-devtools-vendor
Version:
<div align="center"> <h2>electron-devtools-vendor</h2> <img alt="MIT" src="https://img.shields.io/github/license/BlackHole1/electron-devtools-vendor?color=9cf&style=flat-square"> <img alt="GitHub repo size" src="https://img.shields.io/github/r
1,707 lines (1,458 loc) • 311 kB
JavaScript
(function(adapter, env) {
let define = window.define,
requireModule = window.requireModule;
if (typeof define !== 'function' || typeof requireModule !== 'function') {
(function () {
let registry = {},
seen = {};
define = function (name, deps, callback) {
if (arguments.length < 3) {
callback = deps;
deps = [];
}
registry[name] = { deps, callback };
};
requireModule = function (name) {
if (seen[name]) {
return seen[name];
}
let mod = registry[name];
if (!mod) {
throw new Error(`Module: '${name}' not found.`);
}
seen[name] = {};
let deps = mod.deps;
let callback = mod.callback;
let reified = [];
let exports;
for (let i = 0, l = deps.length; i < l; i++) {
if (deps[i] === 'exports') {
reified.push((exports = {}));
} else {
reified.push(requireModule(deps[i]));
}
}
let value = callback.apply(this, reified);
seen[name] = exports || value;
return seen[name];
};
define.registry = registry;
define.seen = seen;
})();
}
define("ember-debug/adapters/basic", ["exports", "ember-debug/utils/on-ready", "ember-debug/utils/ember/array", "ember-debug/utils/ember/object", "ember-debug/utils/rsvp"], function (exports, _onReady, _array, _object, _rsvp) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _object.default.extend({
init() {
(0, _rsvp.resolve)(this.connect(), 'ember-inspector').then(() => {
this.onConnectionReady();
}, null, 'ember-inspector');
this._messageCallbacks = [];
},
/**
* Uses the current build's config module to determine
* the environment.
*
* @property environment
* @type {String}
*/
environment: (0, _object.computed)(function () {
return requireModule('ember-debug/config')['default'].environment;
}),
debug() {
return console.debug(...arguments);
},
log() {
return console.log(...arguments);
},
/**
* A wrapper for `console.warn`.
*
* @method warn
*/
warn() {
return console.warn(...arguments);
},
/**
Used to send messages to EmberExtension
@param {Object} type the message to the send
*/
sendMessage() {},
/**
Register functions to be called
when a message from EmberExtension is received
@param {Function} callback
*/
onMessageReceived(callback) {
this._messageCallbacks.push(callback);
},
/**
Inspect a specific DOM node. This usually
means using the current environment's tools
to inspect the node in the DOM.
For example, in chrome, `inspect(node)`
will open the Elements tab in dev tools
and highlight the DOM node.
@param {Node} node
*/
inspectNode() {},
_messageReceived(message) {
this._messageCallbacks.forEach(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(error) {
if (this.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() {
return new _rsvp.Promise((resolve, reject) => {
(0, _onReady.onReady)(() => {
if (this.isDestroyed) {
reject();
}
this.interval = setInterval(() => {
if (document.documentElement.dataset.emberExtension) {
clearInterval(this.interval);
resolve();
}
}, 10);
});
}, 'ember-inspector');
},
willDestroy() {
this._super();
clearInterval(this.interval);
},
_isReady: false,
_pendingMessages: (0, _object.computed)(function () {
return (0, _array.A)();
}),
send(options) {
if (this._isReady) {
this.sendMessage(...arguments);
} else {
this._pendingMessages.push(options);
}
},
/**
Called when the connection is set up.
Flushes the pending messages.
*/
onConnectionReady() {
// Flush pending messages
const messages = this._pendingMessages;
messages.forEach(options => this.sendMessage(options));
messages.clear();
this._isReady = true;
}
});
});
define("ember-debug/adapters/bookmarklet", ["exports", "ember-debug/adapters/basic"], function (exports, _basic) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _basic.default.extend({
init() {
this._super();
this._listen();
},
sendMessage(options) {
options = options || {};
window.emberInspector.w.postMessage(options, window.emberInspector.url);
},
_listen() {
window.addEventListener('message', e => {
if (e.origin !== window.emberInspector.url) {
return;
}
const message = e.data;
if (message.from === 'devtools') {
this._messageReceived(message);
}
});
window.onunload = () => {
this.sendMessage({
unloading: true
});
};
}
});
});
define("ember-debug/adapters/chrome", ["exports", "ember-debug/adapters/web-extension"], function (exports, _webExtension) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _webExtension.default.extend();
});
define("ember-debug/adapters/firefox", ["exports", "ember-debug/adapters/web-extension"], function (exports, _webExtension) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _webExtension.default.extend({
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(...arguments);
} catch (e) {}
},
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(...arguments);
} catch (e) {}
}
});
});
define("ember-debug/adapters/web-extension", ["exports", "ember-debug/adapters/basic", "ember-debug/utils/type-check", "ember-debug/utils/ember", "ember-debug/utils/ember/runloop"], function (exports, _basic, _typeCheck, _ember, _runloop) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const {
isArray
} = Array;
const {
keys
} = Object;
exports.default = _basic.default.extend({
init() {
this.set('_channel', new MessageChannel());
this.set('_chromePort', this.get('_channel.port1'));
this._super(...arguments);
},
connect() {
const channel = this._channel;
return this._super(...arguments).then(() => {
window.postMessage('debugger-client', '*', [channel.port2]);
this._listen();
}, null, 'ember-inspector');
},
sendMessage(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.
options = deepClone(options);
this._chromePort.postMessage(options);
},
/**
* Open the devtools "Elements" and select an DOM node.
*
* @param {Node} node The DOM node to select
*/
inspectNode(node) {
// NOTE:
//
// Basically, we are just trying to call `inspect(node)` here.
// However, `inspect` is a special function that is in the global
// scope but not on the global object (i.e. `window.inspect`) does
// not work. This sometimes causes problems, because, e.g. if the
// page has a div with the ID `inspect`, `window.inspect` will point
// to that div and shadow the "global" inspect function with no way
// to get it back. That causes "`inspect` is not a function" errors.
//
// As it turns out, however, when the extension page evals, the
// `inspect` function does not get shadowed. So, we can ask the
// inspector extension page to call that function for us, using
// `inspected.Window.eval('inspect(node)')`.
//
// However, since we cannot just send the DOM node directly to the
// extension, we will have to store it in a temporary global variable
// so that the extension can find it.
let name = `__EMBER_INSPECTOR_${(Math.random() * 100000000).toFixed(0)}`;
window[name] = node;
this.get('namespace.port').send('view:inspectDOMNode', {
name
});
},
_listen() {
let chromePort = this._chromePort;
chromePort.addEventListener('message', event => {
const message = event.data; // We should generally not be run-wrapping here. Starting a runloop in
// ember-debug will cause the inspected app to revalidate/rerender. We
// are generally not intending to cause changes to the rendered output
// of the app, so this is generally unnecessary, and in big apps this
// could be quite slow. There is nothing special about the `view:*`
// messages – I (GC) just happened to have reviewed all of them recently
// and can be quite sure that they don't need the runloop. We should
// audit the rest of them and see if we can remove the else branch. I
// think we most likely can. In the limited cases (if any) where the
// runloop is needed, the callback code should just do the wrapping
// themselves.
if (message.type.startsWith('view:')) {
this._messageReceived(message);
} else {
(0, _runloop.run)(() => {
this._messageReceived(message);
});
}
});
chromePort.start();
}
});
// On some older Ember version `Ember.ENV.EXTEND_PROTOTYPES` is not
// guarenteed to be an object. While this code only support 3.4+ (all
// of which normalizes `EXTEND_PROTOTYPES` for us), startup-wrapper.js
// eagerly require/load ember-debug modules, which ultimately causes
// this top-level code to run, even we are going to pick a different
// adapter later. See GH #1114.
const HAS_ARRAY_PROTOTYPE_EXTENSIONS = (() => {
try {
return _ember.default.ENV.EXTEND_PROTOTYPES.Array === true;
} catch (e) {
return false;
}
})();
let deepClone;
if (HAS_ARRAY_PROTOTYPE_EXTENSIONS) {
deepClone = function deepClone(item) {
return item;
};
} else {
/**
* 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}
*/
deepClone = function deepClone(item) {
let clone = item;
if (isArray(item)) {
clone = new Array(item.length);
item.forEach((child, key) => {
clone[key] = deepClone(child);
});
} else if (item && (0, _typeCheck.typeOf)(item) === 'object') {
clone = {};
keys(item).forEach(key => {
clone[key] = deepClone(item[key]);
});
}
return clone;
};
}
});
define("ember-debug/adapters/websocket", ["exports", "ember-debug/adapters/basic", "ember-debug/utils/on-ready", "ember-debug/utils/ember/object", "ember-debug/utils/ember/runloop", "ember-debug/utils/rsvp"], function (exports, _basic, _onReady, _object, _runloop, _rsvp) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _basic.default.extend({
sendMessage(options = {}) {
this.socket.emit('emberInspectorMessage', options);
},
socket: (0, _object.computed)(function () {
return window.EMBER_INSPECTOR_CONFIG.remoteDebugSocket;
}),
_listen() {
this.socket.on('emberInspectorMessage', message => {
// We should generally not be run-wrapping here. Starting a runloop in
// ember-debug will cause the inspected app to revalidate/rerender. We
// are generally not intending to cause changes to the rendered output
// of the app, so this is generally unnecessary, and in big apps this
// could be quite slow. There is nothing special about the `view:*`
// messages – I (GC) just happened to have reviewed all of them recently
// and can be quite sure that they don't need the runloop. We should
// audit the rest of them and see if we can remove the else branch. I
// think we most likely can. In the limited cases (if any) where the
// runloop is needed, the callback code should just do the wrapping
// themselves.
if (message.type.startsWith('view:')) {
this._messageReceived(message);
} else {
(0, _runloop.run)(() => {
this._messageReceived(message);
});
}
});
},
_disconnect() {
this.socket.removeAllListeners('emberInspectorMessage');
},
connect() {
return new _rsvp.Promise((resolve, reject) => {
(0, _onReady.onReady)(() => {
if (this.isDestroyed) {
reject();
}
const EMBER_INSPECTOR_CONFIG = window.EMBER_INSPECTOR_CONFIG;
if (typeof EMBER_INSPECTOR_CONFIG === 'object' && EMBER_INSPECTOR_CONFIG.remoteDebugSocket) {
resolve();
}
});
}).then(() => {
this._listen();
});
},
willDestroy() {
this._disconnect();
}
});
});
define("ember-debug/container-debug", ["exports", "ember-debug/debug-port", "ember-debug/utils/ember/object", "ember-debug/utils/ember/object/computed"], function (exports, _debugPort, _object, _computed) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _debugPort.default.extend({
namespace: null,
objectInspector: (0, _computed.readOnly)('namespace.objectInspector'),
container: (0, _computed.reads)('namespace.owner.__container__'),
portNamespace: 'container',
TYPES_TO_SKIP: (0, _object.computed)(function () {
return ['component-lookup', 'container-debug-adapter', 'resolver-for-debugging', 'event_dispatcher'];
}),
typeFromKey(key) {
return key.split(':').shift();
},
nameFromKey(key) {
return key.split(':').pop();
},
shouldHide(type) {
return type[0] === '-' || this.TYPES_TO_SKIP.indexOf(type) !== -1;
},
instancesByType() {
let key;
let instancesByType = {};
let cache = this.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) {
const 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() {
let key;
let types = [];
const instancesByType = this.instancesByType();
for (key in instancesByType) {
types.push({
name: key,
count: instancesByType[key].length
});
}
return types;
},
getInstances(type) {
const instances = this.instancesByType()[type];
if (!instances) {
return null;
}
return instances.map(item => ({
name: this.nameFromKey(item.fullName),
fullName: item.fullName,
inspectable: this.objectInspector.canSend(item.instance)
}));
},
messages: {
getTypes() {
this.sendMessage('types', {
types: this.getTypes()
});
},
getInstances(message) {
let instances = this.getInstances(message.containerType);
if (instances) {
this.sendMessage('instances', {
instances,
status: 200
});
} else {
this.sendMessage('instances', {
status: 404
});
}
},
sendInstanceToConsole(message) {
const instance = this.container.lookup(message.name);
this.objectToConsole.sendValueToConsole(instance);
}
}
});
});
define("ember-debug/data-debug", ["exports", "ember-debug/debug-port", "ember-debug/utils/ember/array", "ember-debug/utils/ember/object", "ember-debug/utils/ember/object/computed", "ember-debug/utils/ember/object/internals"], function (exports, _debugPort, _array, _object, _computed, _internals) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _debugPort.default.extend({
init() {
this._super();
this.sentTypes = {};
this.sentRecords = {};
},
releaseTypesMethod: null,
releaseRecordsMethod: null,
/* eslint-disable ember/no-side-effects */
adapter: (0, _object.computed)('namespace.owner', function () {
const owner = this.get('namespace.owner'); // dataAdapter:main is deprecated
let adapter = this._resolve('data-adapter:main') && owner.lookup('data-adapter:main'); // column limit is now supported at the inspector level
if (adapter) {
(0, _object.set)(adapter, 'attributeLimit', 100);
return adapter;
}
return null;
}),
/* eslint-enable ember/no-side-effects */
_resolve(name) {
const owner = this.get('namespace.owner');
return owner.resolveRegistration(name);
},
namespace: null,
port: (0, _computed.alias)('namespace.port'),
objectInspector: (0, _computed.alias)('namespace.objectInspector'),
portNamespace: 'data',
modelTypesAdded(types) {
let typesToSend;
typesToSend = types.map(type => this.wrapType(type));
this.sendMessage('modelTypesAdded', {
modelTypes: typesToSend
});
},
modelTypesUpdated(types) {
let typesToSend = types.map(type => this.wrapType(type));
this.sendMessage('modelTypesUpdated', {
modelTypes: typesToSend
});
},
wrapType(type) {
const objectId = (0, _internals.guidFor)(type.object);
this.sentTypes[objectId] = type;
return {
columns: type.columns,
count: type.count,
name: type.name,
objectId
};
},
recordsAdded(recordsReceived) {
let records = recordsReceived.map(record => this.wrapRecord(record));
this.sendMessage('recordsAdded', {
records
});
},
recordsUpdated(recordsReceived) {
let records = recordsReceived.map(record => this.wrapRecord(record));
this.sendMessage('recordsUpdated', {
records
});
},
recordsRemoved(index, count) {
this.sendMessage('recordsRemoved', {
index,
count
});
},
wrapRecord(record) {
const objectId = (0, _internals.guidFor)(record.object);
let columnValues = {};
let searchKeywords = [];
this.sentRecords[objectId] = record; // make objects clonable
for (let i in record.columnValues) {
columnValues[i] = this.objectInspector.inspect(record.columnValues[i]);
} // make sure keywords can be searched and clonable
searchKeywords = (0, _array.A)(record.searchKeywords).filter(keyword => typeof keyword === 'string' || typeof keyword === 'number');
return {
columnValues,
searchKeywords,
filterValues: record.filterValues,
color: record.color,
objectId
};
},
releaseTypes() {
if (this.releaseTypesMethod) {
this.releaseTypesMethod();
this.releaseTypesMethod = null;
this.sentTypes = {};
}
},
releaseRecords() {
if (this.releaseRecordsMethod) {
this.releaseRecordsMethod();
this.releaseRecordsMethod = null;
this.sentRecords = {};
}
},
willDestroy() {
this._super();
this.releaseRecords();
this.releaseTypes();
},
messages: {
checkAdapter() {
this.sendMessage('hasAdapter', {
hasAdapter: !!this.adapter
});
},
getModelTypes() {
this.releaseTypes();
this.releaseTypesMethod = this.adapter.watchModelTypes(types => {
this.modelTypesAdded(types);
}, types => {
this.modelTypesUpdated(types);
});
},
releaseModelTypes() {
this.releaseTypes();
},
getRecords(message) {
const type = this.sentTypes[message.objectId];
this.releaseRecords();
let typeOrName;
if (this.get('adapter.acceptsModelName')) {
// Ember >= 1.3
typeOrName = type.name;
}
let releaseMethod = this.adapter.watchRecords(typeOrName, recordsReceived => {
this.recordsAdded(recordsReceived);
}, recordsUpdated => {
this.recordsUpdated(recordsUpdated);
}, (...args) => {
this.recordsRemoved(...args);
});
this.releaseRecordsMethod = releaseMethod;
},
releaseRecords() {
this.releaseRecords();
},
inspectModel(message) {
this.objectInspector.sendObject(this.sentRecords[message.objectId].object);
},
getFilters() {
this.sendMessage('filters', {
filters: this.adapter.getFilters()
});
}
}
});
});
define("ember-debug/debug-port", ["exports", "ember-debug/utils/ember/object"], function (exports, _object) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _object.default.extend({
port: null,
messages: {},
portNamespace: null,
init() {
this._super(...arguments);
this.set('port', this.get('namespace.port'));
this.setupOrRemovePortListeners('on');
},
willDestroy() {
this._super(...arguments);
this.setupOrRemovePortListeners('off');
},
sendMessage(name, message) {
this.port.send(this.messageName(name), message);
},
messageName(name) {
let messageName = name;
if (this.portNamespace) {
messageName = `${this.portNamespace}:${messageName}`;
}
return messageName;
},
/**
* Setup or tear down port listeners. Call on `init` and `willDestroy`
* @param {String} onOrOff 'on' or 'off' the functions to call i.e. port.on or port.off for adding or removing listeners
*/
setupOrRemovePortListeners(onOrOff) {
let port = this.port;
let messages = this.messages;
for (let name in messages) {
if (messages.hasOwnProperty(name)) {
port[onOrOff](this.messageName(name), this, messages[name]);
}
}
}
});
});
define("ember-debug/deprecation-debug", ["exports", "ember-debug/debug-port", "ember-debug/libs/source-map", "ember-debug/utils/ember/array", "ember-debug/utils/ember/debug", "ember-debug/utils/ember/object", "ember-debug/utils/ember/object/computed", "ember-debug/utils/ember/object/internals", "ember-debug/utils/ember/runloop", "ember-debug/utils/rsvp"], function (exports, _debugPort, _sourceMap, _array, _debug, _object, _computed, _internals, _runloop, _rsvp) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _debugPort.default.extend({
portNamespace: 'deprecation',
adapter: (0, _computed.readOnly)('port.adapter'),
sourceMap: (0, _object.computed)(function () {
return _sourceMap.default.create();
}),
emberCliConfig: (0, _computed.readOnly)('namespace.generalDebug.emberCliConfig'),
init() {
this._super();
this.deprecations = (0, _array.A)();
this.deprecationsToSend = (0, _array.A)();
this.groupedDeprecations = {};
this.options = {
toggleDeprecationWorkflow: false
};
this.handleDeprecations();
},
/**
* Checks if ember-cli and looks for source maps.
*/
fetchSourceMap(stackStr) {
if (this.emberCliConfig && this.get('emberCliConfig.environment') === 'development') {
return this.sourceMap.map(stackStr).then(mapped => {
if (mapped && mapped.length > 0) {
let source = mapped.find(item => 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 (0, _rsvp.resolve)(null, 'ember-inspector');
}
},
sendPending() {
if (this.isDestroyed) {
return;
}
let deprecations = (0, _array.A)();
let promises = (0, _rsvp.all)(this.deprecationsToSend.map(deprecation => {
let obj;
let promise = (0, _rsvp.resolve)(undefined, 'ember-inspector');
let grouped = this.groupedDeprecations;
this.deprecations.pushObject(deprecation);
const id = (0, _internals.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 = (0, _array.A)();
grouped[id] = obj;
}
let found = obj.sources.findBy('stackStr', deprecation.stackStr);
if (!found) {
let stackStr = deprecation.stackStr;
promise = this.fetchSourceMap(stackStr).then(map => {
obj.sources.pushObject({
map,
stackStr
});
if (map) {
obj.hasSourceMap = true;
}
}, null, 'ember-inspector');
}
return promise.then(() => {
delete obj.stackStr;
deprecations.addObject(obj);
}, null, 'ember-inspector');
}));
promises.then(() => {
this.sendMessage('deprecationsAdded', {
deprecations
});
this.deprecationsToSend.clear();
this.sendCount();
}, null, 'ember-inspector');
},
sendCount() {
if (this.isDestroyed) {
return;
}
this.sendMessage('count', {
count: this.get('deprecations.length') + this.get('deprecationsToSend.length')
});
},
messages: {
watch() {
this._watching = true;
let grouped = this.groupedDeprecations;
let deprecations = [];
for (let i in grouped) {
if (!grouped.hasOwnProperty(i)) {
continue;
}
deprecations.push(grouped[i]);
}
this.sendMessage('deprecationsAdded', {
deprecations
});
this.sendPending();
},
sendStackTraces(message) {
let deprecation = message.deprecation;
deprecation.sources.forEach(source => {
let stack = source.stackStr;
stack = stack.split('\n');
stack.unshift(`Ember Inspector (Deprecation Trace): ${deprecation.message || ''}`);
this.adapter.log(stack.join('\n'));
});
},
getCount() {
this.sendCount();
},
clear() {
(0, _runloop.cancel)(this.debounce);
this.deprecations.clear();
this.set('groupedDeprecations', {});
this.sendCount();
},
release() {
this._watching = false;
},
setOptions({
options
}) {
this.options.toggleDeprecationWorkflow = options.toggleDeprecationWorkflow;
}
},
willDestroy() {
(0, _runloop.cancel)(this.debounce);
return this._super(...arguments);
},
handleDeprecations() {
(0, _debug.registerDeprecationHandler)((message, options, next) => {
if (!this.adapter) {
next(message, options);
return;
}
/* global __fail__*/
let error; // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
try {
__fail__.fail();
} catch (e) {
error = e;
}
let stack;
let 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 ')}`;
}
let url;
if (options && typeof options === 'object') {
url = options.url;
}
const deprecation = {
message,
stackStr,
url
}; // For ember-debug testing we usually don't want
// to catch deprecations
if (!this.namespace.IGNORE_DEPRECATIONS) {
this.deprecationsToSend.pushObject(deprecation);
(0, _runloop.cancel)(this.debounce);
if (this._watching) {
this.debounce = (0, _runloop.debounce)(this, 'sendPending', 100);
} else {
this.debounce = (0, _runloop.debounce)(this, 'sendCount', 100);
}
if (!this._warned) {
this.adapter.warn('Deprecations were detected, see the Ember Inspector deprecations tab for more details.');
this._warned = true;
}
}
if (this.options.toggleDeprecationWorkflow) {
next(message, options);
}
});
}
});
});
define("ember-debug/general-debug", ["exports", "ember-debug/debug-port", "ember-debug/utils/ember"], function (exports, _debugPort, _ember) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _debugPort.default.extend({
/**
* Fetches the ember-cli configuration info and sets them on
* the `emberCliConfig` property.
*/
init() {
this._super(...arguments);
let found = findMetaTag('name', /environment$/);
if (found) {
try {
let config = JSON.parse(unescape(found.getAttribute('content')));
this.set('emberCliConfig', config);
} catch (e) {}
}
},
/**
* Passed on creation.
*
* @type {EmberDebug}
*/
namespace: null,
/**
* Used by the DebugPort
*
* @type {String}
*/
portNamespace: 'general',
/**
* Set on creation.
* Contains ember-cli configuration info.
*
* Info used to determine the file paths of an ember-cli app.
*
* @return {Object}
* {String} environment ex: 'development'
* {String} modulePrefix ex: 'my-app'
* {String} podModulePrefix ex: 'my-app/pods'
* {Boolean} usePodsByDefault
*/
emberCliConfig: null,
/**
* Sends a reply back indicating if the app has been booted.
*
* `__inspector__booted` is a property set on the application instance
* when the ember-debug is inserted into the target app.
* see: startup-wrapper.
*/
sendBooted() {
this.sendMessage('applicationBooted', {
booted: this.get('namespace.owner.__inspector__booted')
});
},
/**
* Sends a reply back indicating that ember-debug has been reset.
* We need to reset ember-debug to remove state between tests.
*/
sendReset() {
this.sendMessage('reset');
},
messages: {
/**
* Called from the inspector to check if the inspected app has been booted.
*/
applicationBooted() {
this.sendBooted();
},
/**
* Called from the inspector to fetch the libraries that are displayed in
* the info tab.
*/
getLibraries() {
this.sendMessage('libraries', {
libraries: _ember.default.libraries._registry
});
},
getEmberCliConfig() {
this.sendMessage('emberCliConfig', {
emberCliConfig: this.emberCliConfig
});
},
/**
* Called from the inspector to refresh the inspected app.
* Used in case the inspector was opened late and therefore missed capturing
* all info.
*/
refresh() {
window.location.reload();
}
}
});
/**
* Finds a meta tag by searching through a certain meta attribute.
*
* @param {String} attribute
* @param {RegExp} regExp
* @return {Element}
*/
function findMetaTag(attribute, regExp = /.*/) {
let metas = document.querySelectorAll(`meta[${attribute}]`);
for (let i = 0; i < metas.length; i++) {
let match = metas[i].getAttribute(attribute).match(regExp);
if (match) {
return metas[i];
}
}
return null;
}
});
define("ember-debug/libs/capture-render-tree", ["exports", "ember-debug/utils/version", "ember-debug/utils/ember"], function (exports, _version, _ember) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/* eslint-disable no-console, no-inner-declarations */
let captureRenderTree; // Ember 3.14+ comes with debug render tree, but the version in 3.14.0/3.14.1 is buggy
if (_ember.default._captureRenderTree && (0, _version.compareVersion)(_ember.default.VERSION, '3.14.1') > 0) {
if (_ember.default.ENV._DEBUG_RENDER_TREE) {
captureRenderTree = _ember.default._captureRenderTree;
} else {
captureRenderTree = function captureRenderTree() {
return [];
};
}
} else {
/**
* Best-effort polyfill for `Ember._captureRenderTree`.
*
* Just like the Ember API, it takes an owner (`ApplicationInstance`, specifically)
* and return an array of render nodes:
*
* interface CapturedRenderNode {
* id: string;
* type: 'outlet' | 'engine' | 'route-template' | 'component';
* name: string;
* args: {
* named: Dict<unknown>;
* positional: unknown[];
* };
* instance: unknown;
* template: Option<string>;
* bounds: Option<{
* parentElement: Simple.Element;
* firstNode: Simple.Node;
* lastNode: Simple.Node;
* }>;
* children: CapturedRenderNode[];
* }
*
* While the API is identical, there are some differences and limitations:
*
* 1. `args` property is not available (it always report empty args).
* 2. `bounds` property is only available on component nodes (`null` everywhere else).
* 3. `{{mount}}` does not insert an `engine` node.
* 4. `Ember.Component` (classic components) are the only type of component in the tree
* (other components are skipped over).
* 5. Ordering of `children` may be different (but this is also not guarenteed in the
* Ember API).
*/
const {
Controller,
ViewUtils,
get,
getOwner,
guidFor
} = _ember.default;
const {
getRootViews,
getChildViews,
getViewBounds
} = ViewUtils;
/**
* We are building the final tree by doing the following steps:
*
* 1. Get the "outlet state" tree from the router.
* 2. Collect the "top level" components. That is, components rendered directly from within
* a route template.
* 3. Do an "interleaved walk" down the outlet and (classic) component tree and map things
* into render nodes.
* 4. Return the array of render nodes we captured.
*
* Usually, this function returns an array of exactly one render node, which is the "root"
* outlet. However, sometimes there may be other top-level components in the app (e.g.
* rendered using the `Ember.Component#appendTo` API).
*/
captureRenderTree = function captureRenderTree(owner) {
let tree = [];
let outletState = getOutletState(owner);
let components = getTopLevelComponents(owner);
if (outletState && components) {
tree.push(captureOutlet('root', owner, components, outletState));
}
return tree;
};
/**
* Get the "outlet state" tree from the router. It corresponds to the "settled",
* app state after resolving all the hooks, redirects, etc. The rendering layer
* takes this tree from the router and render it on screen.
*
* It has the following format:
*
* interface OutletState {
* render: {
* // The current owner, could be the app or an engine
* owner: Owner;
*
* // The name of the route
* name: string;
*
* // The controller for the route
* controller: Controller;
*
* // The template (or template factory?) for the route (can this really be undefined?)
* template: OwnedTemplate | undefined;
*
* // The name of the outlet this was rendered into (in the parent route template)
* outlet: string;
*
* // The name of the parent route (we don't use this)
* into: string | undefined;
* },
*
* // The children outlets of this route, keyed by the outlet names (e.g. "main", "sidebar", ...)
* outlets: Dict<OutletState | undefined>;
* }
*
* This function returns the "root" outlet state.
*/
function getOutletState(owner) {
try {
// eslint-disable-next-line ember/no-private-routing-service
return owner.lookup('router:main')._toplevelView.state.ref.value();
} catch (error) {
console.log('[Ember Inspector] failed to capture render tree');
console.log(error);
return undefined;
}
}
/**
* Collect the "top level" components. That is, components rendered directly
* from within a route template.
*
* We do this by walking the classic component tree and identify components
* that has its "target" (~= the parent template's `{{this}}` object) set to
* a controller (or undefined, for root components rendered outside of the
* application route).
*
* This function returns a `Map` keyed by controllers (`undefiend` is also a
* possible key) to arrays of top-level components for that route/controller.
*/
function getTopLevelComponents(owner) {
try {
let map = new Map();
collectComponentsByController(map, null, getRootViews(owner));
return map;
} catch (error) {
console.log('[Ember Inspector] failed to capture render tree');
console.log(error);
return undefined;
}
}
/**
* Returns the "target" of a (classic) component.
*/
function targetForComponent(component) {
return get(component, '_target') || get(component, '_targetObject');
}
/**
* Recursively walk an array of components and add any "top level" components
* to the map keyed by their controller.
*/
function collectComponentsByController(map, controller, components) {
components.forEach(component => {
let target = targetForComponent(component);
if (target === undefined || target instanceof Controller) {
/**
* If our parent is already added, don't add ourself again.
*
* This is to prevent something like this:
*
* {{!-- app/templates/application.hbs}}
* <Parent>
* <Child />
* </Parent>
*
* Without this check, both the parent and the yielded child will be
* considered "top level" since they both have the controller as their
* target.
*/
if (target !== controller) {
if (!map.has(target)) {
map.set(target, []);
}
map.get(target).push(component);
}
collectComponentsByController(map, target, getChildViews(component));
} else {
collectComponentsByController(map, controller, getChildViews(component));
}
});
}
const EMPTY_ARGS = {
named: Object.create(null),
positional: []
};
/**
* Return the module name (e.g. `my-app/templates/application.hbs`) for a
* template or template factory, if available. This may not be present for,
* e.g. templates compiled using the "inline" `hbs` tagged string method.
*/
function nameForTemplate(template) {
if (template.meta) {
// Factory
return template.meta.moduleName || null;
} else if (template.referrer) {
// Instance
return template.referrer.moduleName || null;
} else {
return null;
}
}
/**
* Walk an outlet tree (the last parameter) and map its content into render nodes.
*
* For each level of the outlet tree, we also have to walk the (classic) component
* tree to attach any components for the current level (and their children) to the
* resulting render nodes tree.
*
* We also check if the owner has changed between the current level and the previous
* level, and if so, we infer that we must have just crossed an engine boundary and
* insert an engine render node to account for that.
*
* Because we don't have a good way to generate a stable ID for the outlet nodes, we
* also pass down a "path" of the routes/outlets we have encountered so far which we
* use to generate the ID.
*/
function captureOutlet(path, owner, components, {
outlets,
render
}) {
let outlet = {
id: `render-node:${path}@${render.outlet}`,
type: 'outlet',
name: render.outlet,
args: EMPTY_ARGS,
instance: undefined,
template: null,
bounds: null,
children: []
};
let parent = outlet;
if (owner !== render.owner) {
let engine = {
id: `render-node:${guidFor(render.owner)}`,
type: 'engine',
name: render.owner.mountPoint,
args: EMPTY_ARGS,
instance: render.owner,
template: null,
bounds: null,
children: []
};
parent.children.push(engine);
parent = engine;
}
let subpath = `${path}@${render.outlet}/${render.name}`;
let route = {
id: `render-node:${subpath}`,
type: 'route-template',
name: render.name,
args: EMPTY_ARGS,
instance: render.controller,
template: nameForTemplate(render.template),
bounds: null,
children: []
};
parent.children.push(route);
parent = route;
let childOutlets = Object.keys(outlets).map(name => captureOutlet(subpath, render.owner, components, outlets[name]));
let childComponents = captureComponents(components.get(render.controller) || [], render.controller);
parent.children.push(...mergeOutletChildren(render.controller, childOutlets, childComponents));
return outlet;
}
/**
* Its is possible to nest an outlet inside a component, one pretty common example
* is a "layout" component:
*
* <SidebarWrapper>
* {{outlet "sidebar"}}
* </SidebarWrapper>
*
* On the other hand, it's not possible to put a component inside an outlet anymore
* when we get to this point. Try to find a suitable parent for each child outlet
* taking the above into account.
*/
function mergeOutletChildren(controller, outlets, components) {
let merged = [];
for (let outlet of outlets) {
if (controller) {
let parentComponent = findOutletComponentParent(outlet.children);
if (controllerForComponent(parentComponent) === controller) {
let parentNode = findOutletComponentNode(components, parentComponent);
if (parentNode) {
parentNode.children.unshift(outlet);
continue;
}
}
}
merged.push(outlet);
}
merged.push(...components);
return merged;
}
function findOutletComponentParent(nodes) {
let result;
for (let node of nodes) {
if (node.type === 'component') {
result = node.instance.parentView;
} else if (node.type === 'engine' || node.type === 'route-template') {
result = findOutletComponentParent(node.children);
}
if (result !== undefined) {
return result;
}
}
}
function findOutletComponentNode(nodes, instance) {
let result;
for (let node of nodes) {
if (node.type === 'component') {
if (node.instance === instance) {
result = node;
} else {
result = findOutletComponentNode(node.children, instance);
}
}
if (result !== undefined) {
return result;
}
}
}
/**
* Returns the name of a (classic) component.
*/
function nameForComponent(component) {
// remove "component:" prefix
return component._debugContainerKey.slice(10);
}
/**
* Returns the nearest controller of a (classic) component. This is so that we know
* whether a given component belongs to the current level (the route that we are
* processing right now) or not.
*/
function controllerForComponent(component) {
let target = component;
while (target && !(target instanceof Controller)) {
target = targetForComponent(target);
}
return target;
}
/**
* Returns the template (or template factory?) for a (classic) component.
*/
function templateForComponent(component) {
let layout = get(component, 'layout');
if (layout) {
return nameForTemplate(layout);
}
let layoutName = get(component, 'layoutName');
if (layoutName) {
let owner = getOwner(component);
let template = owner.lookup(`template:${layoutName}`);
return nameForTemplate(template);
}
return null;
}
/**
* Return the render node for a given (classic) component, and its children up
* until the next route boundary.
*/
function captureComponents(components, controller) {
return components.filter(component => controllerForComponent(component) === controller).map(component => ({
id: `render-node:${guidFor(component)}`,
type: 'component',
name: nameForComponent(component),
args: EMPTY_ARGS,
instance: component,
template: templateForComponent(component),
bounds: getViewBounds(component),
children: captureComponents(getChildViews(component), controller)
}));
}
}
exports.default = captureRenderTree;
});
define("ember-debug/libs/promise-assembler", ["exports", "ember-debug/models/promise", "ember-debug/utils/ember/array", "ember-debug/utils/ember/object", "ember-debug/utils/ember/object/evented", "ember-debug/utils/ember/utils", "ember-debug/utils/rsvp"], function (exports, _promise, _array, _object, _evented, _utils, _rsvp) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
Original implementation and the idea behind the `PromiseAssembler`,
`Promise` model, and other work related to promise inspection was done
by Stefan Penner (@stefanpenner) thanks to McGraw Hill Education (@mhelabs)
and Yapp Labs (@yapplabs).
*/
let PromiseAssembler = _object.default.extend(_evented.default, {
// RSVP lib to debug
RSVP: _rsvp.default,
isStarted: false,
init() {
this._super(...arguments);
this.all = (0, _array.A)();
this.promiseIndex = {};
},
start() {
this.RSVP.configure('instrument', true);
this.promiseChained = e => {
chain.call(this, e);
};
this.promiseRejected = e => {
reject.call(this, e);
};
this.promiseFulfilled = e => {
fulfill.call(this, e);