UNPKG

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