capybara-ember-inspector 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +2 -0
- data/capybara-ember-inspector.gemspec +26 -0
- data/lib/capybara/ember/inspector.rb +12 -0
- data/lib/capybara/ember/inspector/extension/.gitignore +0 -0
- data/lib/capybara/ember/inspector/extension/background-script.js +74 -0
- data/lib/capybara/ember/inspector/extension/content-script.js +58 -0
- data/lib/capybara/ember/inspector/extension/devtools.html +24 -0
- data/lib/capybara/ember/inspector/extension/devtools.js +5 -0
- data/lib/capybara/ember/inspector/extension/ember_debug/ember_debug.js +3173 -0
- data/lib/capybara/ember/inspector/extension/images/arrow_down.svg +52 -0
- data/lib/capybara/ember/inspector/extension/images/calculate.svg +15 -0
- data/lib/capybara/ember/inspector/extension/images/ember-icon-final.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/fishy_tomster.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/hamster.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/icon128.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/icon16.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/icon19.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/icon38.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/icon48.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/send.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/send_arrow.png +0 -0
- data/lib/capybara/ember/inspector/extension/images/tomster.png +0 -0
- data/lib/capybara/ember/inspector/extension/in-page-script.js +14 -0
- data/lib/capybara/ember/inspector/extension/manifest.json +39 -0
- data/lib/capybara/ember/inspector/extension/options.html +62 -0
- data/lib/capybara/ember/inspector/extension/options.js +26 -0
- data/lib/capybara/ember/inspector/extension/panes/ember_extension.css +1411 -0
- data/lib/capybara/ember/inspector/extension/panes/ember_extension.js +4687 -0
- data/lib/capybara/ember/inspector/extension/panes/index.html +17 -0
- data/lib/capybara/ember/inspector/extension/panes/start.js +3 -0
- data/lib/capybara/ember/inspector/extension/vendor/chrome-bootstrap.css +636 -0
- data/lib/capybara/ember/inspector/extension/vendor/ember.js +46943 -0
- data/lib/capybara/ember/inspector/extension/vendor/ember.prod.js +46498 -0
- data/lib/capybara/ember/inspector/extension/vendor/handlebars.js +2278 -0
- data/lib/capybara/ember/inspector/extension/vendor/jquery.js +9555 -0
- data/lib/capybara/ember/inspector/extension/vendor/list-view.prod.js +1437 -0
- data/lib/capybara/ember/inspector/extension/vendor/loader.js +41 -0
- data/lib/capybara/ember/inspector/extension/vendor/resolver.js +188 -0
- data/lib/capybara/ember/inspector/version.rb +7 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6eb56fdc8ba70d877c55a6ca542df82c4d12981c
|
4
|
+
data.tar.gz: 03605ec8dc77cdbff26360095f22de230429ecde
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1065370242abe2cad2ec6ed41efb5d79a99dcc11609f737f7f7a9a26c293fa37146a6c25c91ef9a3f76f254af1e7f0c8d55a925c25cb1dd4c05c6260f803a46
|
7
|
+
data.tar.gz: 7eb4ef24052ce57844d9891464fd21165ea5f2453b015f95421198fd5acb4c6e97c9bd7d15ffaaadae580c8e4777b3f2845c9f146e73f0e9a08207271b7ff175
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Attila Györffy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Capybara::Ember::Inspector
|
2
|
+
|
3
|
+
Adds Ember Inspector capable Selenium Driver into your Capybara tests for convenient debugging
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
group :test do
|
11
|
+
gem 'capybara-ember-inspector', require: false
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install capybara-ember-inspector
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Require `capybara/ember/inspector` in your test file, for example in `rails_helper.rb` or `spec_helper.rb` to set up Capybara's `:selenium` Driver to run your tests in Chrome with the Ember Inspector extension already enabled. This allows you to pause your tests at any time and activeate the inspector within Chrome, just like you would during development.
|
26
|
+
|
27
|
+
## Licensing
|
28
|
+
|
29
|
+
This gem contains a pre-built version of the [Ember Inspector](https://github.com/emberjs/ember-inspector) source code that is licensed under the [MIT License](https://github.com/emberjs/ember-inspector/blob/master/LICENSE) and is subject to copyrights.
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it ( https://github.com/[my-github-username]/capybara-ember-inspector/fork )
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'capybara/ember/inspector/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "capybara-ember-inspector"
|
8
|
+
spec.version = Capybara::Ember::Inspector::VERSION
|
9
|
+
spec.authors = ["Attila Györffy"]
|
10
|
+
spec.email = ["attila@attilagyorffy.com"]
|
11
|
+
spec.summary = %q{Capybara and Ember (Tomster) sitting on a tree.}
|
12
|
+
spec.description = %q{Adds Ember Inspector capable Selenium Driver into your Capybara tests for convenient debugging}
|
13
|
+
spec.homepage = "https://github.com/liquid/capybara-ember-inspector"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_runtime_dependency "capybara"
|
24
|
+
spec.add_runtime_dependency "selenium-webdriver"
|
25
|
+
spec.add_runtime_dependency "chromedriver-helper"
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "capybara/ember/inspector/version"
|
2
|
+
|
3
|
+
Capybara.register_driver :selenium do |app|
|
4
|
+
extension = File.expand_path('../inspector/extension', __FILE__)
|
5
|
+
|
6
|
+
Capybara::Selenium::Driver.new(app,
|
7
|
+
browser: :chrome,
|
8
|
+
switches: [
|
9
|
+
"--load-extension=#{extension}"
|
10
|
+
]
|
11
|
+
)
|
12
|
+
end
|
File without changes
|
@@ -0,0 +1,74 @@
|
|
1
|
+
/*global chrome*/
|
2
|
+
(function() {
|
3
|
+
"use strict";
|
4
|
+
|
5
|
+
var activeTabs = {},
|
6
|
+
ports = {};
|
7
|
+
|
8
|
+
function generateVersionsTooltip(versions) {
|
9
|
+
return versions.map(function(lib) {
|
10
|
+
return lib.name + " " + lib.version;
|
11
|
+
}).join("\n");
|
12
|
+
}
|
13
|
+
|
14
|
+
function setActionTitle(tabId){
|
15
|
+
chrome.pageAction.setTitle({
|
16
|
+
tabId: tabId,
|
17
|
+
title: generateVersionsTooltip(activeTabs[tabId])
|
18
|
+
});
|
19
|
+
}
|
20
|
+
|
21
|
+
function updateTabAction(tabId){
|
22
|
+
chrome.storage.sync.get("options", function(data) {
|
23
|
+
if (!data.options.showTomster) { return; }
|
24
|
+
chrome.pageAction.show(tabId);
|
25
|
+
setActionTitle(tabId);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
function hideAction(tabId){
|
30
|
+
delete activeTabs[tabId];
|
31
|
+
chrome.pageAction.hide(tabId);
|
32
|
+
}
|
33
|
+
|
34
|
+
chrome.extension.onMessage.addListener(function(request, sender) {
|
35
|
+
if (!sender.tab) {
|
36
|
+
// noop
|
37
|
+
} else if (request && request.type === 'emberVersion') {
|
38
|
+
activeTabs[sender.tab.id] = request.versions;
|
39
|
+
updateTabAction(sender.tab.id);
|
40
|
+
} else if (request && request.type === 'resetEmberIcon') {
|
41
|
+
hideAction(sender.tab.id);
|
42
|
+
} else {
|
43
|
+
var port = ports[sender.tab.id];
|
44
|
+
if (port) { port.postMessage(request); }
|
45
|
+
}
|
46
|
+
});
|
47
|
+
|
48
|
+
chrome.extension.onConnect.addListener(function(port) {
|
49
|
+
var appId;
|
50
|
+
|
51
|
+
port.onMessage.addListener(function(message) {
|
52
|
+
if (message.appId) {
|
53
|
+
appId = message.appId;
|
54
|
+
|
55
|
+
ports[appId] = port;
|
56
|
+
|
57
|
+
port.onDisconnect.addListener(function() {
|
58
|
+
delete ports[appId];
|
59
|
+
});
|
60
|
+
} else if (message.from === 'devtools') {
|
61
|
+
chrome.tabs.sendMessage(appId, message);
|
62
|
+
}
|
63
|
+
});
|
64
|
+
});
|
65
|
+
|
66
|
+
chrome.tabs.onUpdated.addListener(function(tabId){
|
67
|
+
// Re-render the Tomster when a tab changes.
|
68
|
+
if (activeTabs[tabId]) {
|
69
|
+
updateTabAction(tabId);
|
70
|
+
}
|
71
|
+
|
72
|
+
});
|
73
|
+
|
74
|
+
}());
|
@@ -0,0 +1,58 @@
|
|
1
|
+
(function() {
|
2
|
+
|
3
|
+
"use strict";
|
4
|
+
|
5
|
+
window.addEventListener('message', function(event) {
|
6
|
+
if (event.data === 'debugger-client') {
|
7
|
+
var port = event.ports[0];
|
8
|
+
listenToPort(port);
|
9
|
+
} else if (event.data.type) {
|
10
|
+
chrome.extension.sendMessage(event.data);
|
11
|
+
}
|
12
|
+
});
|
13
|
+
|
14
|
+
function listenToPort(port) {
|
15
|
+
port.addEventListener('message', function(event) {
|
16
|
+
chrome.extension.sendMessage(event.data);
|
17
|
+
});
|
18
|
+
|
19
|
+
chrome.extension.onMessage.addListener(function(message) {
|
20
|
+
if (message.from === 'devtools') {
|
21
|
+
port.postMessage(message);
|
22
|
+
}
|
23
|
+
});
|
24
|
+
|
25
|
+
port.start();
|
26
|
+
}
|
27
|
+
|
28
|
+
// let ember-debug know that content script has executed
|
29
|
+
document.documentElement.dataset.emberExtension = 1;
|
30
|
+
|
31
|
+
|
32
|
+
// clear a possible previous Ember icon
|
33
|
+
chrome.extension.sendMessage({ type: 'resetEmberIcon' });
|
34
|
+
|
35
|
+
// inject JS into the page to check for an app on domready
|
36
|
+
var script = document.createElement('script');
|
37
|
+
script.type = "text/javascript";
|
38
|
+
script.src = chrome.extension.getURL("in-page-script.js");
|
39
|
+
if (document.body) {
|
40
|
+
document.body.appendChild(script);
|
41
|
+
script.onload = function() {
|
42
|
+
document.body.removeChild(script);
|
43
|
+
};
|
44
|
+
}
|
45
|
+
|
46
|
+
var iframes = document.getElementsByTagName('iframe');
|
47
|
+
var urls = [];
|
48
|
+
for (var i = 0, l = iframes.length; i < l; i ++) {
|
49
|
+
urls.push(iframes[i].src);
|
50
|
+
}
|
51
|
+
|
52
|
+
// FIXME
|
53
|
+
setTimeout(function() {
|
54
|
+
chrome.extension.sendMessage({type: 'iframes', urls: urls});
|
55
|
+
}, 500);
|
56
|
+
|
57
|
+
|
58
|
+
}());
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<style>
|
5
|
+
body {
|
6
|
+
min-width: 357px;
|
7
|
+
overflow-x: hidden;
|
8
|
+
}
|
9
|
+
|
10
|
+
img {
|
11
|
+
margin: 5px;
|
12
|
+
border: 2px solid black;
|
13
|
+
vertical-align: middle;
|
14
|
+
width: 75px;
|
15
|
+
height: 75px;
|
16
|
+
}
|
17
|
+
</style>
|
18
|
+
|
19
|
+
<script src="devtools.js"></script>
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
</body>
|
23
|
+
</html>
|
24
|
+
|
@@ -0,0 +1,3173 @@
|
|
1
|
+
(function(adapter) {
|
2
|
+
|
3
|
+
if (typeof define !== 'function' && typeof requireModule !== 'function') {
|
4
|
+
var define, requireModule;
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
var registry = {}, seen = {};
|
8
|
+
|
9
|
+
define = function(name, deps, callback) {
|
10
|
+
registry[name] = { deps: deps, callback: callback };
|
11
|
+
};
|
12
|
+
|
13
|
+
requireModule = function(name) {
|
14
|
+
if (seen[name]) { return seen[name]; }
|
15
|
+
seen[name] = {};
|
16
|
+
|
17
|
+
var mod = registry[name];
|
18
|
+
|
19
|
+
if (!mod) {
|
20
|
+
throw new Error("Module: '" + name + "' not found.");
|
21
|
+
}
|
22
|
+
|
23
|
+
var deps = mod.deps,
|
24
|
+
callback = mod.callback,
|
25
|
+
reified = [],
|
26
|
+
exports;
|
27
|
+
|
28
|
+
for (var i=0, l=deps.length; i<l; i++) {
|
29
|
+
if (deps[i] === 'exports') {
|
30
|
+
reified.push(exports = {});
|
31
|
+
} else {
|
32
|
+
reified.push(requireModule(deps[i]));
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
var value = callback.apply(this, reified);
|
37
|
+
return seen[name] = exports || value;
|
38
|
+
};
|
39
|
+
|
40
|
+
define.registry = registry;
|
41
|
+
define.seen = seen;
|
42
|
+
})();
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
This is a wrapper for `ember-debug.js`
|
47
|
+
Wraps the script in a function,
|
48
|
+
and ensures that the script is executed
|
49
|
+
only after the dom is ready
|
50
|
+
and the application has initialized.
|
51
|
+
|
52
|
+
Also responsible for sending the first tree.
|
53
|
+
**/
|
54
|
+
|
55
|
+
var currentAdapter = 'basic';
|
56
|
+
if (typeof adapter !== 'undefined') {
|
57
|
+
currentAdapter = adapter;
|
58
|
+
}
|
59
|
+
|
60
|
+
(function(adapter) {
|
61
|
+
|
62
|
+
// RSVP promise inspection
|
63
|
+
// First thing because of
|
64
|
+
var events = [], callbacks = {};
|
65
|
+
if (!window.__PROMISE_INSTRUMENTATION__) {
|
66
|
+
callbacks = window.__PROMISE_INSTRUMENTATION__ = {};
|
67
|
+
var eventNames = ['created', 'fulfilled', 'rejected', 'chained'];
|
68
|
+
|
69
|
+
for (var i = 0; i < eventNames.length; i++) {
|
70
|
+
(function(eventName) {
|
71
|
+
callbacks[eventName] = function(options) {
|
72
|
+
events.push({
|
73
|
+
eventName: eventName,
|
74
|
+
options: options
|
75
|
+
});
|
76
|
+
};
|
77
|
+
}(eventNames[i]));
|
78
|
+
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
function inject() {
|
84
|
+
window.EmberInspector = Ember.Debug = requireModule('ember_debug')['default'];
|
85
|
+
}
|
86
|
+
|
87
|
+
onEmberReady(function() {
|
88
|
+
if (!window.Ember) {
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
// global to prevent injection
|
92
|
+
if (window.NO_EMBER_DEBUG) {
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
// prevent from injecting twice
|
96
|
+
if (!Ember.Debug) {
|
97
|
+
inject();
|
98
|
+
Ember.Debug.Adapter = requireModule('adapters/' + adapter)['default'];
|
99
|
+
|
100
|
+
onApplicationStart(function() {
|
101
|
+
Ember.Debug.setProperties({
|
102
|
+
existingEvents: events,
|
103
|
+
existingCallbacks: callbacks
|
104
|
+
});
|
105
|
+
Ember.Debug.start();
|
106
|
+
});
|
107
|
+
}
|
108
|
+
});
|
109
|
+
|
110
|
+
function onEmberReady(callback) {
|
111
|
+
onReady(function() {
|
112
|
+
if (window.Ember) {
|
113
|
+
callback();
|
114
|
+
} else {
|
115
|
+
window.addEventListener('Ember.Application', callback, false);
|
116
|
+
}
|
117
|
+
});
|
118
|
+
}
|
119
|
+
|
120
|
+
function onReady(callback) {
|
121
|
+
if (document.readyState === 'complete') {
|
122
|
+
setTimeout(completed);
|
123
|
+
} else {
|
124
|
+
document.addEventListener( "DOMContentLoaded", completed, false);
|
125
|
+
// For some reason DOMContentLoaded doesn't always work
|
126
|
+
window.addEventListener( "load", completed, false );
|
127
|
+
}
|
128
|
+
|
129
|
+
function completed() {
|
130
|
+
document.removeEventListener( "DOMContentLoaded", completed, false );
|
131
|
+
window.removeEventListener( "load", completed, false );
|
132
|
+
callback();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
// There's probably a better way
|
137
|
+
// to determine when the application starts
|
138
|
+
// but this definitely works
|
139
|
+
function onApplicationStart(callback) {
|
140
|
+
if (typeof Ember === 'undefined') {
|
141
|
+
return;
|
142
|
+
}
|
143
|
+
var documentElement = document.documentElement;
|
144
|
+
var interval = setInterval(function() {
|
145
|
+
if ((documentElement.dataset.emberExtension || (EMBER_INSPECTOR_CONFIG && EMBER_INSPECTOR_CONFIG.remoteDebugSocket)) && Ember.BOOTED) {
|
146
|
+
clearInterval(interval);
|
147
|
+
callback();
|
148
|
+
}
|
149
|
+
}, 1);
|
150
|
+
}
|
151
|
+
|
152
|
+
}(currentAdapter));
|
153
|
+
|
154
|
+
define("adapters/basic",
|
155
|
+
["exports"],
|
156
|
+
function(__exports__) {
|
157
|
+
"use strict";
|
158
|
+
var BasicAdapter = Ember.Object.extend({
|
159
|
+
debug: function() {
|
160
|
+
console.debug.apply(console, arguments);
|
161
|
+
},
|
162
|
+
log: function() {
|
163
|
+
console.log.apply(console, arguments);
|
164
|
+
},
|
165
|
+
/**
|
166
|
+
Used to send messages to EmberExtension
|
167
|
+
|
168
|
+
@param {Object} type the message to the send
|
169
|
+
*/
|
170
|
+
sendMessage: function(options) {},
|
171
|
+
|
172
|
+
/**
|
173
|
+
Register functions to be called
|
174
|
+
when a message from EmberExtension is received
|
175
|
+
|
176
|
+
@param {Function} callback
|
177
|
+
*/
|
178
|
+
onMessageReceived: function(callback) {
|
179
|
+
this.get('_messageCallbacks').pushObject(callback);
|
180
|
+
},
|
181
|
+
|
182
|
+
/**
|
183
|
+
Inspect a specific element. This usually
|
184
|
+
means using the current environment's tools
|
185
|
+
to inspect the element in the DOM.
|
186
|
+
|
187
|
+
For example, in chrome, `inspect(elem)`
|
188
|
+
will open the Elements tab in dev tools
|
189
|
+
and highlight the element.
|
190
|
+
|
191
|
+
@param {DOM Element} elem
|
192
|
+
*/
|
193
|
+
inspectElement: function(elem) {},
|
194
|
+
|
195
|
+
_messageCallbacks: Ember.computed(function() { return Ember.A(); }).property(),
|
196
|
+
|
197
|
+
_messageReceived: function(message) {
|
198
|
+
this.get('_messageCallbacks').forEach(function(callback) {
|
199
|
+
callback.call(null, message);
|
200
|
+
});
|
201
|
+
}
|
202
|
+
});
|
203
|
+
|
204
|
+
__exports__["default"] = BasicAdapter;
|
205
|
+
});
|
206
|
+
define("adapters/bookmarklet",
|
207
|
+
["adapters/basic","exports"],
|
208
|
+
function(__dependency1__, __exports__) {
|
209
|
+
"use strict";
|
210
|
+
var BasicAdapter = __dependency1__["default"];
|
211
|
+
var $ = Ember.$;
|
212
|
+
|
213
|
+
__exports__["default"] = BasicAdapter.extend({
|
214
|
+
init: function() {
|
215
|
+
this._super();
|
216
|
+
this._connect();
|
217
|
+
},
|
218
|
+
|
219
|
+
sendMessage: function(options) {
|
220
|
+
options = options || {};
|
221
|
+
window.emberInspector.w.postMessage(options, window.emberInspector.url);
|
222
|
+
},
|
223
|
+
|
224
|
+
_connect: function() {
|
225
|
+
var self = this;
|
226
|
+
window.addEventListener('message', function(e) {
|
227
|
+
if (e.origin !== window.emberInspector.url) {
|
228
|
+
return;
|
229
|
+
}
|
230
|
+
var message = e.data;
|
231
|
+
if (message.from === 'devtools') {
|
232
|
+
self._messageReceived(message);
|
233
|
+
}
|
234
|
+
});
|
235
|
+
|
236
|
+
$(window).on('unload', function() {
|
237
|
+
self.sendMessage({
|
238
|
+
unloading: true
|
239
|
+
});
|
240
|
+
});
|
241
|
+
}
|
242
|
+
});
|
243
|
+
});
|
244
|
+
define("adapters/chrome",
|
245
|
+
["adapters/basic","exports"],
|
246
|
+
function(__dependency1__, __exports__) {
|
247
|
+
"use strict";
|
248
|
+
var BasicAdapter = __dependency1__["default"];
|
249
|
+
|
250
|
+
var ChromeAdapter = BasicAdapter.extend({
|
251
|
+
init: function() {
|
252
|
+
this._super();
|
253
|
+
this._connect();
|
254
|
+
},
|
255
|
+
|
256
|
+
sendMessage: function(options) {
|
257
|
+
options = options || {};
|
258
|
+
this.get('_chromePort').postMessage(options);
|
259
|
+
},
|
260
|
+
|
261
|
+
inspectElement: function(elem) {
|
262
|
+
inspect(elem);
|
263
|
+
},
|
264
|
+
|
265
|
+
_channel: Ember.computed(function() {
|
266
|
+
return new MessageChannel();
|
267
|
+
}).property(),
|
268
|
+
|
269
|
+
_chromePort: Ember.computed(function() {
|
270
|
+
return this.get('_channel.port1');
|
271
|
+
}).property(),
|
272
|
+
|
273
|
+
_connect: function() {
|
274
|
+
var channel = this.get('_channel'),
|
275
|
+
self = this,
|
276
|
+
chromePort = this.get('_chromePort');
|
277
|
+
|
278
|
+
window.postMessage('debugger-client', [channel.port2], '*');
|
279
|
+
|
280
|
+
chromePort.addEventListener('message', function(event) {
|
281
|
+
var message = event.data;
|
282
|
+
Ember.run(function() {
|
283
|
+
self._messageReceived(message);
|
284
|
+
});
|
285
|
+
});
|
286
|
+
|
287
|
+
chromePort.start();
|
288
|
+
|
289
|
+
}
|
290
|
+
});
|
291
|
+
|
292
|
+
__exports__["default"] = ChromeAdapter;
|
293
|
+
});
|
294
|
+
define("adapters/firefox",
|
295
|
+
["adapters/basic","exports"],
|
296
|
+
function(__dependency1__, __exports__) {
|
297
|
+
"use strict";
|
298
|
+
var BasicAdapter = __dependency1__["default"];
|
299
|
+
|
300
|
+
var FirefoxAdapter = BasicAdapter.extend({
|
301
|
+
init: function() {
|
302
|
+
this._super();
|
303
|
+
this._connect();
|
304
|
+
},
|
305
|
+
|
306
|
+
debug: function() {
|
307
|
+
// WORKAROUND: temporarily workaround issues with firebug console object:
|
308
|
+
// - https://github.com/tildeio/ember-extension/issues/94
|
309
|
+
// - https://github.com/firebug/firebug/pull/109
|
310
|
+
// - https://code.google.com/p/fbug/issues/detail?id=7045
|
311
|
+
try {
|
312
|
+
this._super.apply(this, arguments);
|
313
|
+
} catch(e) { }
|
314
|
+
},
|
315
|
+
log: function() {
|
316
|
+
// WORKAROUND: temporarily workaround issues with firebug console object:
|
317
|
+
// - https://github.com/tildeio/ember-extension/issues/94
|
318
|
+
// - https://github.com/firebug/firebug/pull/109
|
319
|
+
// - https://code.google.com/p/fbug/issues/detail?id=7045
|
320
|
+
try {
|
321
|
+
this._super.apply(this, arguments);
|
322
|
+
} catch(e) { }
|
323
|
+
},
|
324
|
+
|
325
|
+
sendMessage: function(options) {
|
326
|
+
options = options || {};
|
327
|
+
var event = document.createEvent("CustomEvent");
|
328
|
+
event.initCustomEvent("ember-debug-send", true, true, options);
|
329
|
+
document.documentElement.dispatchEvent(event);
|
330
|
+
},
|
331
|
+
|
332
|
+
inspectElement: function(elem) {
|
333
|
+
this.sendMessage({
|
334
|
+
type: 'view:devtools:inspectDOMElement',
|
335
|
+
elementSelector: "#" + elem.getAttribute('id')
|
336
|
+
});
|
337
|
+
},
|
338
|
+
|
339
|
+
_connect: function() {
|
340
|
+
var self = this;
|
341
|
+
|
342
|
+
window.addEventListener('ember-debug-receive', function(event) {
|
343
|
+
var message = event.detail;
|
344
|
+
Ember.run(function() {
|
345
|
+
// FIX: needed to fix permission denied exception on Firefox >= 30
|
346
|
+
// - https://github.com/emberjs/ember-inspector/issues/147
|
347
|
+
// - https://blog.mozilla.org/addons/2014/04/10/changes-to-unsafewindow-for-the-add-on-sdk/
|
348
|
+
switch (typeof message) {
|
349
|
+
case "string":
|
350
|
+
message = JSON.parse(message);
|
351
|
+
break;
|
352
|
+
case "object":
|
353
|
+
break;
|
354
|
+
default:
|
355
|
+
throw new Error("ember-debug-receive: string or object expected");
|
356
|
+
}
|
357
|
+
self._messageReceived(message);
|
358
|
+
});
|
359
|
+
});
|
360
|
+
}
|
361
|
+
|
362
|
+
});
|
363
|
+
|
364
|
+
__exports__["default"] = FirefoxAdapter;
|
365
|
+
});
|
366
|
+
define("adapters/websocket",
|
367
|
+
["adapters/basic","exports"],
|
368
|
+
function(__dependency1__, __exports__) {
|
369
|
+
"use strict";
|
370
|
+
var BasicAdapter = __dependency1__["default"];
|
371
|
+
|
372
|
+
var computed = Ember.computed;
|
373
|
+
|
374
|
+
var WebsocketAdapter = BasicAdapter.extend({
|
375
|
+
init: function() {
|
376
|
+
this._super();
|
377
|
+
this._connect();
|
378
|
+
},
|
379
|
+
|
380
|
+
sendMessage: function(options) {
|
381
|
+
options = options || {};
|
382
|
+
this.get('socket').emit('emberInspectorMessage', options);
|
383
|
+
},
|
384
|
+
|
385
|
+
socket: computed(function() {
|
386
|
+
return window.EMBER_INSPECTOR_CONFIG.remoteDebugSocket;
|
387
|
+
}).property(),
|
388
|
+
|
389
|
+
_connect: function() {
|
390
|
+
var self = this;
|
391
|
+
this.get('socket').on('emberInspectorMessage', function(message) {
|
392
|
+
Ember.run(function() {
|
393
|
+
self._messageReceived(message);
|
394
|
+
});
|
395
|
+
});
|
396
|
+
},
|
397
|
+
|
398
|
+
_disconnect: function() {
|
399
|
+
this.get('socket').removeAllListeners("emberInspectorMessage");
|
400
|
+
},
|
401
|
+
|
402
|
+
willDestroy: function() {
|
403
|
+
this._disconnect();
|
404
|
+
}
|
405
|
+
});
|
406
|
+
|
407
|
+
__exports__["default"] = WebsocketAdapter;
|
408
|
+
});
|
409
|
+
define("container_debug",
|
410
|
+
["mixins/port_mixin","exports"],
|
411
|
+
function(__dependency1__, __exports__) {
|
412
|
+
"use strict";
|
413
|
+
var PortMixin = __dependency1__["default"];
|
414
|
+
|
415
|
+
var EmberObject = Ember.Object;
|
416
|
+
var computed = Ember.computed;
|
417
|
+
var oneWay = computed.oneWay;
|
418
|
+
|
419
|
+
__exports__["default"] = EmberObject.extend(PortMixin, {
|
420
|
+
namespace: null,
|
421
|
+
|
422
|
+
port: oneWay('namespace.port').readOnly(),
|
423
|
+
application: oneWay('namespace.application').readOnly(),
|
424
|
+
objectInspector: oneWay('namespace.objectInspector').readOnly(),
|
425
|
+
|
426
|
+
container: computed(function() {
|
427
|
+
return this.get('application.__container__');
|
428
|
+
}).property('application'),
|
429
|
+
|
430
|
+
portNamespace: 'container',
|
431
|
+
|
432
|
+
TYPES_TO_SKIP: computed(function() {
|
433
|
+
return [
|
434
|
+
'component-lookup',
|
435
|
+
'container-debug-adapter',
|
436
|
+
'resolver-for-debugging',
|
437
|
+
'event_dispatcher'
|
438
|
+
];
|
439
|
+
}).property(),
|
440
|
+
|
441
|
+
typeFromKey: function(key) {
|
442
|
+
return key.split(':').shift();
|
443
|
+
},
|
444
|
+
|
445
|
+
nameFromKey: function(key) {
|
446
|
+
return key.split(':').pop();
|
447
|
+
},
|
448
|
+
|
449
|
+
shouldHide: function(type) {
|
450
|
+
return type[0] === '-' || this.get('TYPES_TO_SKIP').indexOf(type) !== -1;
|
451
|
+
},
|
452
|
+
|
453
|
+
instancesByType: function() {
|
454
|
+
var key, instancesByType = {};
|
455
|
+
var cache = this.get('container').cache;
|
456
|
+
// Detect if InheritingDict (from Ember < 1.8)
|
457
|
+
if (typeof cache.dict !== 'undefined' && typeof cache.eachLocal !== 'undefined') {
|
458
|
+
cache = cache.dict;
|
459
|
+
}
|
460
|
+
for (key in cache) {
|
461
|
+
var type = this.typeFromKey(key);
|
462
|
+
if (this.shouldHide(type) ){ continue; }
|
463
|
+
if (instancesByType[type] === undefined) {
|
464
|
+
instancesByType[type] = [];
|
465
|
+
}
|
466
|
+
instancesByType[type].push({
|
467
|
+
fullName: key,
|
468
|
+
instance: cache[key]
|
469
|
+
});
|
470
|
+
}
|
471
|
+
return instancesByType;
|
472
|
+
},
|
473
|
+
|
474
|
+
getTypes: function() {
|
475
|
+
var key, types = [];
|
476
|
+
var instancesByType = this.instancesByType();
|
477
|
+
for (key in instancesByType) {
|
478
|
+
types.push({ name: key, count: instancesByType[key].length });
|
479
|
+
}
|
480
|
+
return types;
|
481
|
+
},
|
482
|
+
|
483
|
+
getInstances: function(type) {
|
484
|
+
var instancesByType = this.instancesByType();
|
485
|
+
return instancesByType[type].map(function(item) {
|
486
|
+
return {
|
487
|
+
name: this.nameFromKey(item.fullName),
|
488
|
+
fullName: item.fullName,
|
489
|
+
inspectable: this.get('objectInspector').canSend(item.instance)
|
490
|
+
};
|
491
|
+
}.bind(this));
|
492
|
+
},
|
493
|
+
|
494
|
+
messages: {
|
495
|
+
getTypes: function() {
|
496
|
+
this.sendMessage('types', {
|
497
|
+
types: this.getTypes()
|
498
|
+
});
|
499
|
+
},
|
500
|
+
getInstances: function(message) {
|
501
|
+
this.sendMessage('instances', {
|
502
|
+
instances: this.getInstances(message.containerType)
|
503
|
+
});
|
504
|
+
},
|
505
|
+
sendInstanceToConsole: function(message) {
|
506
|
+
var instance = this.get('container').lookup(message.name);
|
507
|
+
this.get('objectToConsole').sendValueToConsole(instance);
|
508
|
+
}
|
509
|
+
}
|
510
|
+
});
|
511
|
+
});
|
512
|
+
define("data_debug",
|
513
|
+
["mixins/port_mixin","exports"],
|
514
|
+
function(__dependency1__, __exports__) {
|
515
|
+
"use strict";
|
516
|
+
var PortMixin = __dependency1__["default"];
|
517
|
+
|
518
|
+
var DataDebug = Ember.Object.extend(PortMixin, {
|
519
|
+
init: function() {
|
520
|
+
this._super();
|
521
|
+
this.sentTypes = {};
|
522
|
+
this.sentRecords = {};
|
523
|
+
},
|
524
|
+
|
525
|
+
sentTypes: {},
|
526
|
+
sentRecords: {},
|
527
|
+
|
528
|
+
releaseTypesMethod: null,
|
529
|
+
releaseRecordsMethod: null,
|
530
|
+
|
531
|
+
adapter: Ember.computed(function() {
|
532
|
+
var container = this.get('application').__container__;
|
533
|
+
// dataAdapter:main is deprecated
|
534
|
+
return (container.resolve('data-adapter:main') && container.lookup('data-adapter:main')) ||
|
535
|
+
(container.resolve('dataAdapter:main') && container.lookup('dataAdapter:main'));
|
536
|
+
}).property('application'),
|
537
|
+
|
538
|
+
namespace: null,
|
539
|
+
|
540
|
+
port: Ember.computed.alias('namespace.port'),
|
541
|
+
application: Ember.computed.alias('namespace.application'),
|
542
|
+
objectInspector: Ember.computed.alias('namespace.objectInspector'),
|
543
|
+
|
544
|
+
portNamespace: 'data',
|
545
|
+
|
546
|
+
modelTypesAdded: function(types) {
|
547
|
+
var self = this, typesToSend;
|
548
|
+
typesToSend = types.map(function(type) {
|
549
|
+
return self.wrapType(type);
|
550
|
+
});
|
551
|
+
this.sendMessage('modelTypesAdded', {
|
552
|
+
modelTypes: typesToSend
|
553
|
+
});
|
554
|
+
},
|
555
|
+
|
556
|
+
modelTypesUpdated: function(types) {
|
557
|
+
var self = this;
|
558
|
+
var typesToSend = types.map(function(type) {
|
559
|
+
return self.wrapType(type);
|
560
|
+
});
|
561
|
+
self.sendMessage('modelTypesUpdated', {
|
562
|
+
modelTypes: typesToSend
|
563
|
+
});
|
564
|
+
},
|
565
|
+
|
566
|
+
wrapType: function(type) {
|
567
|
+
var objectId = Ember.guidFor(type.object);
|
568
|
+
this.sentTypes[objectId] = type;
|
569
|
+
|
570
|
+
return {
|
571
|
+
columns: type.columns,
|
572
|
+
count: type.count,
|
573
|
+
name: type.name,
|
574
|
+
objectId: objectId
|
575
|
+
};
|
576
|
+
},
|
577
|
+
|
578
|
+
|
579
|
+
recordsAdded: function(recordsReceived) {
|
580
|
+
var self = this, records;
|
581
|
+
records = recordsReceived.map(function(record) {
|
582
|
+
return self.wrapRecord(record);
|
583
|
+
});
|
584
|
+
self.sendMessage('recordsAdded', {
|
585
|
+
records: records
|
586
|
+
});
|
587
|
+
},
|
588
|
+
|
589
|
+
recordsUpdated: function(recordsReceived) {
|
590
|
+
var self = this;
|
591
|
+
var records = recordsReceived.map(function(record) {
|
592
|
+
return self.wrapRecord(record);
|
593
|
+
});
|
594
|
+
self.sendMessage('recordsUpdated', {
|
595
|
+
records: records
|
596
|
+
});
|
597
|
+
},
|
598
|
+
|
599
|
+
recordsRemoved: function(idx, count) {
|
600
|
+
this.sendMessage('recordsRemoved', {
|
601
|
+
index: idx,
|
602
|
+
count: count
|
603
|
+
});
|
604
|
+
},
|
605
|
+
|
606
|
+
wrapRecord: function(record) {
|
607
|
+
var objectId = Ember.guidFor(record.object);
|
608
|
+
var self = this;
|
609
|
+
var columnValues = {};
|
610
|
+
var searchKeywords = [];
|
611
|
+
this.sentRecords[objectId] = record;
|
612
|
+
// make objects clonable
|
613
|
+
for (var i in record.columnValues) {
|
614
|
+
columnValues[i] = this.get('objectInspector').inspect(record.columnValues[i]);
|
615
|
+
}
|
616
|
+
// make sure keywords can be searched and clonable
|
617
|
+
searchKeywords = Ember.A(record.searchKeywords).filter(function(keyword) {
|
618
|
+
return (typeof keyword === 'string' || typeof keyword === 'number');
|
619
|
+
});
|
620
|
+
return {
|
621
|
+
columnValues: columnValues,
|
622
|
+
searchKeywords: searchKeywords,
|
623
|
+
filterValues: record.filterValues,
|
624
|
+
color: record.color,
|
625
|
+
objectId: objectId
|
626
|
+
};
|
627
|
+
},
|
628
|
+
|
629
|
+
releaseTypes: function() {
|
630
|
+
if(this.releaseTypesMethod) {
|
631
|
+
this.releaseTypesMethod();
|
632
|
+
this.releaseTypesMethod = null;
|
633
|
+
this.sentTypes = {};
|
634
|
+
}
|
635
|
+
},
|
636
|
+
|
637
|
+
releaseRecords: function(typeObjectId) {
|
638
|
+
if (this.releaseRecordsMethod) {
|
639
|
+
this.releaseRecordsMethod();
|
640
|
+
this.releaseRecordsMethod = null;
|
641
|
+
this.sentRecords = {};
|
642
|
+
}
|
643
|
+
},
|
644
|
+
|
645
|
+
willDestroy: function() {
|
646
|
+
this._super();
|
647
|
+
this.releaseRecords();
|
648
|
+
this.releaseTypes();
|
649
|
+
},
|
650
|
+
|
651
|
+
messages: {
|
652
|
+
checkAdapter: function() {
|
653
|
+
this.sendMessage('hasAdapter', { hasAdapter: !!this.get('adapter') });
|
654
|
+
},
|
655
|
+
|
656
|
+
getModelTypes: function() {
|
657
|
+
var self = this;
|
658
|
+
this.releaseTypes();
|
659
|
+
this.releaseTypesMethod = this.get('adapter').watchModelTypes(
|
660
|
+
function(types) {
|
661
|
+
self.modelTypesAdded(types);
|
662
|
+
}, function(types) {
|
663
|
+
self.modelTypesUpdated(types);
|
664
|
+
});
|
665
|
+
},
|
666
|
+
|
667
|
+
releaseModelTypes: function() {
|
668
|
+
this.releaseTypes();
|
669
|
+
},
|
670
|
+
|
671
|
+
getRecords: function(message) {
|
672
|
+
var type = this.sentTypes[message.objectId], self = this;
|
673
|
+
this.releaseRecords();
|
674
|
+
|
675
|
+
var releaseMethod = this.get('adapter').watchRecords(type.object,
|
676
|
+
function(recordsReceived) {
|
677
|
+
self.recordsAdded(recordsReceived);
|
678
|
+
},
|
679
|
+
function(recordsUpdated) {
|
680
|
+
self.recordsUpdated(recordsUpdated);
|
681
|
+
},
|
682
|
+
function() {
|
683
|
+
self.recordsRemoved.apply(self, arguments);
|
684
|
+
}
|
685
|
+
);
|
686
|
+
this.releaseRecordsMethod = releaseMethod;
|
687
|
+
},
|
688
|
+
|
689
|
+
releaseRecords: function() {
|
690
|
+
this.releaseRecords();
|
691
|
+
},
|
692
|
+
|
693
|
+
inspectModel: function(message) {
|
694
|
+
this.get('objectInspector').sendObject(this.sentRecords[message.objectId].object);
|
695
|
+
},
|
696
|
+
|
697
|
+
getFilters: function() {
|
698
|
+
this.sendMessage('filters', {
|
699
|
+
filters: this.get('adapter').getFilters()
|
700
|
+
});
|
701
|
+
}
|
702
|
+
}
|
703
|
+
});
|
704
|
+
|
705
|
+
__exports__["default"] = DataDebug;
|
706
|
+
});
|
707
|
+
define("ember_debug",
|
708
|
+
["adapters/basic","port","object_inspector","general_debug","render_debug","view_debug","route_debug","data_debug","promise_debug","container_debug","exports"],
|
709
|
+
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
|
710
|
+
"use strict";
|
711
|
+
var BasicAdapter = __dependency1__["default"];
|
712
|
+
var Port = __dependency2__["default"];
|
713
|
+
var ObjectInspector = __dependency3__["default"];
|
714
|
+
var GeneralDebug = __dependency4__["default"];
|
715
|
+
var RenderDebug = __dependency5__["default"];
|
716
|
+
var ViewDebug = __dependency6__["default"];
|
717
|
+
var RouteDebug = __dependency7__["default"];
|
718
|
+
var DataDebug = __dependency8__["default"];
|
719
|
+
var PromiseDebug = __dependency9__["default"];
|
720
|
+
var ContainerDebug = __dependency10__["default"];
|
721
|
+
|
722
|
+
var EmberDebug;
|
723
|
+
|
724
|
+
EmberDebug = Ember.Namespace.extend({
|
725
|
+
|
726
|
+
application: null,
|
727
|
+
started: false,
|
728
|
+
|
729
|
+
Port: Port,
|
730
|
+
Adapter: BasicAdapter,
|
731
|
+
|
732
|
+
|
733
|
+
// These two are used to make RSVP start instrumentation
|
734
|
+
// even before this object is created
|
735
|
+
// all events triggered before creation are injected
|
736
|
+
// to this object as `existingEvents`
|
737
|
+
existingEvents: Ember.computed(function() { return []; }).property(),
|
738
|
+
existingCallbacks: Ember.computed(function() { return {}; }).property(),
|
739
|
+
|
740
|
+
start: function() {
|
741
|
+
if (this.get('started')) {
|
742
|
+
this.reset();
|
743
|
+
return;
|
744
|
+
}
|
745
|
+
this.set('started', true);
|
746
|
+
|
747
|
+
this.set('application', getApplication());
|
748
|
+
|
749
|
+
this.reset();
|
750
|
+
|
751
|
+
this.get("adapter").debug("Ember Inspector Active");
|
752
|
+
},
|
753
|
+
|
754
|
+
destroyContainer: function() {
|
755
|
+
var self = this;
|
756
|
+
['dataDebug',
|
757
|
+
'viewDebug',
|
758
|
+
'routeDebug',
|
759
|
+
'objectInspector',
|
760
|
+
'generalDebug',
|
761
|
+
'renderDebug',
|
762
|
+
'promiseDebug',
|
763
|
+
'containerDebug',
|
764
|
+
].forEach(function(prop) {
|
765
|
+
var handler = self.get(prop);
|
766
|
+
if (handler) {
|
767
|
+
Ember.run(handler, 'destroy');
|
768
|
+
self.set(prop, null);
|
769
|
+
}
|
770
|
+
});
|
771
|
+
},
|
772
|
+
|
773
|
+
startModule: function(prop, Module) {
|
774
|
+
this.set(prop, Module.create({ namespace: this }));
|
775
|
+
},
|
776
|
+
|
777
|
+
reset: function() {
|
778
|
+
this.destroyContainer();
|
779
|
+
Ember.run(this, function() {
|
780
|
+
|
781
|
+
this.startModule('adapter', this.Adapter);
|
782
|
+
this.startModule('port', this.Port);
|
783
|
+
|
784
|
+
this.startModule('generalDebug', GeneralDebug);
|
785
|
+
this.startModule('renderDebug', RenderDebug);
|
786
|
+
this.startModule('objectInspector', ObjectInspector);
|
787
|
+
this.startModule('routeDebug', RouteDebug);
|
788
|
+
this.startModule('viewDebug', ViewDebug);
|
789
|
+
this.startModule('dataDebug', DataDebug);
|
790
|
+
this.startModule('promiseDebug', PromiseDebug);
|
791
|
+
this.startModule('containerDebug', ContainerDebug);
|
792
|
+
|
793
|
+
this.generalDebug.sendBooted();
|
794
|
+
this.viewDebug.sendTree();
|
795
|
+
});
|
796
|
+
},
|
797
|
+
|
798
|
+
inspect: function(obj) {
|
799
|
+
this.get('objectInspector').sendObject(obj);
|
800
|
+
this.get('adapter').log('Sent to the Object Inspector');
|
801
|
+
return obj;
|
802
|
+
}
|
803
|
+
|
804
|
+
}).create();
|
805
|
+
|
806
|
+
function getApplication() {
|
807
|
+
var namespaces = Ember.Namespace.NAMESPACES,
|
808
|
+
application;
|
809
|
+
|
810
|
+
namespaces.forEach(function(namespace) {
|
811
|
+
if(namespace instanceof Ember.Application) {
|
812
|
+
application = namespace;
|
813
|
+
return false;
|
814
|
+
}
|
815
|
+
});
|
816
|
+
return application;
|
817
|
+
}
|
818
|
+
|
819
|
+
__exports__["default"] = EmberDebug;
|
820
|
+
});
|
821
|
+
define("general_debug",
|
822
|
+
["mixins/port_mixin","exports"],
|
823
|
+
function(__dependency1__, __exports__) {
|
824
|
+
"use strict";
|
825
|
+
var PortMixin = __dependency1__["default"];
|
826
|
+
|
827
|
+
var GeneralDebug = Ember.Object.extend(PortMixin, {
|
828
|
+
namespace: null,
|
829
|
+
|
830
|
+
port: Ember.computed.alias('namespace.port'),
|
831
|
+
|
832
|
+
application: Ember.computed.alias('namespace.application'),
|
833
|
+
|
834
|
+
promiseDebug: Ember.computed.alias('namespace.promiseDebug'),
|
835
|
+
|
836
|
+
portNamespace: 'general',
|
837
|
+
|
838
|
+
sendBooted: function() {
|
839
|
+
this.sendMessage('applicationBooted', {
|
840
|
+
booted: Ember.BOOTED
|
841
|
+
});
|
842
|
+
},
|
843
|
+
|
844
|
+
messages: {
|
845
|
+
applicationBooted: function() {
|
846
|
+
this.sendBooted();
|
847
|
+
},
|
848
|
+
getLibraries: function() {
|
849
|
+
var libraries = arrayize(Ember.libraries);
|
850
|
+
this.sendMessage('libraries', { libraries: libraries });
|
851
|
+
},
|
852
|
+
refresh: function() {
|
853
|
+
window.location.reload();
|
854
|
+
}
|
855
|
+
}
|
856
|
+
});
|
857
|
+
|
858
|
+
function arrayize(enumerable) {
|
859
|
+
return Ember.A(enumerable).map(function(item) {
|
860
|
+
return item;
|
861
|
+
});
|
862
|
+
}
|
863
|
+
|
864
|
+
__exports__["default"] = GeneralDebug;
|
865
|
+
});
|
866
|
+
define("libs/promise_assembler",
|
867
|
+
["models/promise","exports"],
|
868
|
+
function(__dependency1__, __exports__) {
|
869
|
+
"use strict";
|
870
|
+
/**
|
871
|
+
Original implementation and the idea behind the `PromiseAssembler`,
|
872
|
+
`Promise` model, and other work related to promise inspection was done
|
873
|
+
by Stefan Penner (@stefanpenner) thanks to McGraw Hill Education (@mhelabs)
|
874
|
+
and Yapp Labs (@yapplabs).
|
875
|
+
*/
|
876
|
+
|
877
|
+
var Promise = __dependency1__["default"];
|
878
|
+
|
879
|
+
var get = Ember.get;
|
880
|
+
var alias = Ember.computed.alias;
|
881
|
+
|
882
|
+
var PromiseAssembler = Ember.Object.extend(Ember.Evented, {
|
883
|
+
// RSVP lib to debug
|
884
|
+
RSVP: Ember.RSVP,
|
885
|
+
|
886
|
+
all: Ember.computed(function() { return Ember.A(); }).property(),
|
887
|
+
|
888
|
+
promiseIndex: Ember.computed(function() { return {}; }).property(),
|
889
|
+
|
890
|
+
// injected on creation
|
891
|
+
promiseDebug: null,
|
892
|
+
|
893
|
+
existingEvents: alias('promiseDebug.existingEvents'),
|
894
|
+
existingCallbacks: alias('promiseDebug.existingCallbacks'),
|
895
|
+
|
896
|
+
start: function() {
|
897
|
+
this.RSVP.configure('instrument', true);
|
898
|
+
var self = this;
|
899
|
+
|
900
|
+
this.promiseChained = function(e) {
|
901
|
+
chain.call(self, e);
|
902
|
+
};
|
903
|
+
this.promiseRejected = function(e) {
|
904
|
+
reject.call(self, e);
|
905
|
+
};
|
906
|
+
this.promiseFulfilled = function(e) {
|
907
|
+
fulfill.call(self, e);
|
908
|
+
};
|
909
|
+
this.promiseCreated = function(e) {
|
910
|
+
create.bind(self)(e);
|
911
|
+
};
|
912
|
+
|
913
|
+
|
914
|
+
this.RSVP.on('chained', this.promiseChained);
|
915
|
+
this.RSVP.on('rejected', this.promiseRejected);
|
916
|
+
this.RSVP.on('fulfilled', this.promiseFulfilled);
|
917
|
+
this.RSVP.on('created', this.promiseCreated);
|
918
|
+
|
919
|
+
if (this.get('existingEvents')) {
|
920
|
+
var callbacks = this.get('existingCallbacks');
|
921
|
+
for (var eventName in callbacks) {
|
922
|
+
this.RSVP.off(eventName, callbacks[eventName]);
|
923
|
+
}
|
924
|
+
var events = Ember.A(this.get('existingEvents'));
|
925
|
+
events.forEach(function(e) {
|
926
|
+
self['promise' + Ember.String.capitalize(e.eventName)].call(self, e.options);
|
927
|
+
});
|
928
|
+
}
|
929
|
+
},
|
930
|
+
|
931
|
+
stop: function() {
|
932
|
+
this.RSVP.configure('instrument', false);
|
933
|
+
this.RSVP.off('chained', this.promiseChained);
|
934
|
+
this.RSVP.off('rejected', this.promiseRejected);
|
935
|
+
this.RSVP.off('fulfilled', this.promiseFulfilled);
|
936
|
+
this.RSVP.off('created', this.promiseCreated);
|
937
|
+
|
938
|
+
this.get('all').forEach(function(item) {
|
939
|
+
item.destroy();
|
940
|
+
});
|
941
|
+
this.set('all', Ember.A());
|
942
|
+
this.set('promiseIndex', {});
|
943
|
+
|
944
|
+
this.promiseChained = null;
|
945
|
+
this.promiseRejected = null;
|
946
|
+
this.promiseFulfilled = null;
|
947
|
+
this.promiseCreated = null;
|
948
|
+
},
|
949
|
+
|
950
|
+
willDestroy: function() {
|
951
|
+
this.stop();
|
952
|
+
this._super();
|
953
|
+
},
|
954
|
+
|
955
|
+
createPromise: function(props) {
|
956
|
+
var promise = Promise.create(props),
|
957
|
+
index = this.get('all.length');
|
958
|
+
|
959
|
+
this.get('all').pushObject(promise);
|
960
|
+
this.get('promiseIndex')[promise.get('guid')] = index;
|
961
|
+
return promise;
|
962
|
+
},
|
963
|
+
|
964
|
+
find: function(guid){
|
965
|
+
if (guid) {
|
966
|
+
var index = this.get('promiseIndex')[guid];
|
967
|
+
if (index !== undefined) {
|
968
|
+
return this.get('all').objectAt(index);
|
969
|
+
}
|
970
|
+
} else {
|
971
|
+
return this.get('all');
|
972
|
+
}
|
973
|
+
},
|
974
|
+
|
975
|
+
findOrCreate: function(guid) {
|
976
|
+
return this.find(guid) || this.createPromise({
|
977
|
+
guid: guid
|
978
|
+
});
|
979
|
+
},
|
980
|
+
|
981
|
+
updateOrCreate: function(guid, properties){
|
982
|
+
var entry = this.find(guid);
|
983
|
+
if (entry) {
|
984
|
+
entry.setProperties(properties);
|
985
|
+
} else {
|
986
|
+
properties = Ember.copy(properties);
|
987
|
+
properties.guid = guid;
|
988
|
+
entry = this.createPromise(properties);
|
989
|
+
}
|
990
|
+
|
991
|
+
return entry;
|
992
|
+
}
|
993
|
+
});
|
994
|
+
|
995
|
+
__exports__["default"] = PromiseAssembler;
|
996
|
+
|
997
|
+
PromiseAssembler.reopenClass({
|
998
|
+
supported: function() {
|
999
|
+
return !!Ember.RSVP.on;
|
1000
|
+
}
|
1001
|
+
});
|
1002
|
+
|
1003
|
+
var fulfill = function(event) {
|
1004
|
+
var guid = event.guid;
|
1005
|
+
var promise = this.updateOrCreate(guid, {
|
1006
|
+
label: event.label,
|
1007
|
+
settledAt: event.timeStamp,
|
1008
|
+
state: 'fulfilled',
|
1009
|
+
value: event.detail
|
1010
|
+
});
|
1011
|
+
this.trigger('fulfilled', {
|
1012
|
+
promise: promise
|
1013
|
+
});
|
1014
|
+
};
|
1015
|
+
|
1016
|
+
|
1017
|
+
var reject = function(event) {
|
1018
|
+
var guid = event.guid;
|
1019
|
+
var promise = this.updateOrCreate(guid, {
|
1020
|
+
label: event.label,
|
1021
|
+
settledAt: event.timeStamp,
|
1022
|
+
state: 'rejected',
|
1023
|
+
reason: event.detail
|
1024
|
+
});
|
1025
|
+
this.trigger('rejected', {
|
1026
|
+
promise: promise
|
1027
|
+
});
|
1028
|
+
};
|
1029
|
+
|
1030
|
+
function chain(event) {
|
1031
|
+
/*jshint validthis:true */
|
1032
|
+
var guid = event.guid,
|
1033
|
+
promise = this.updateOrCreate(guid, {
|
1034
|
+
label: event.label,
|
1035
|
+
chainedAt: event.timeStamp
|
1036
|
+
}),
|
1037
|
+
children = promise.get('children'),
|
1038
|
+
child = this.findOrCreate(event.childGuid);
|
1039
|
+
|
1040
|
+
child.set('parent', promise);
|
1041
|
+
children.pushObject(child);
|
1042
|
+
|
1043
|
+
this.trigger('chained', {
|
1044
|
+
promise: promise,
|
1045
|
+
child: child
|
1046
|
+
});
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
function create(event) {
|
1050
|
+
/*jshint validthis:true */
|
1051
|
+
var guid = event.guid;
|
1052
|
+
|
1053
|
+
var promise = this.updateOrCreate(guid, {
|
1054
|
+
label: event.label,
|
1055
|
+
createdAt: event.timeStamp,
|
1056
|
+
stack: event.stack
|
1057
|
+
});
|
1058
|
+
|
1059
|
+
// todo fix ordering
|
1060
|
+
if (Ember.isNone(promise.get('state'))) {
|
1061
|
+
promise.set('state', 'created');
|
1062
|
+
}
|
1063
|
+
this.trigger('created', {
|
1064
|
+
promise: promise
|
1065
|
+
});
|
1066
|
+
}
|
1067
|
+
});
|
1068
|
+
define("mixins/port_mixin",
|
1069
|
+
["exports"],
|
1070
|
+
function(__exports__) {
|
1071
|
+
"use strict";
|
1072
|
+
__exports__["default"] = Ember.Mixin.create({
|
1073
|
+
port: null,
|
1074
|
+
messages: {},
|
1075
|
+
|
1076
|
+
portNamespace: null,
|
1077
|
+
|
1078
|
+
init: function() {
|
1079
|
+
this.setupPortListeners();
|
1080
|
+
},
|
1081
|
+
|
1082
|
+
willDestroy: function() {
|
1083
|
+
this.removePortListeners();
|
1084
|
+
},
|
1085
|
+
|
1086
|
+
sendMessage: function(name, message) {
|
1087
|
+
this.get('port').send(this.messageName(name), message);
|
1088
|
+
},
|
1089
|
+
|
1090
|
+
setupPortListeners: function() {
|
1091
|
+
var port = this.get('port'),
|
1092
|
+
self = this,
|
1093
|
+
messages = this.get('messages');
|
1094
|
+
|
1095
|
+
for (var name in messages) {
|
1096
|
+
if(messages.hasOwnProperty(name)) {
|
1097
|
+
port.on(this.messageName(name), this, messages[name]);
|
1098
|
+
}
|
1099
|
+
}
|
1100
|
+
},
|
1101
|
+
|
1102
|
+
removePortListeners: function() {
|
1103
|
+
var port = this.get('port'),
|
1104
|
+
self = this,
|
1105
|
+
messages = this.get('messages');
|
1106
|
+
|
1107
|
+
for (var name in messages) {
|
1108
|
+
if(messages.hasOwnProperty(name)) {
|
1109
|
+
port.off(this.messageName(name), this, messages[name]);
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
},
|
1113
|
+
|
1114
|
+
messageName: function(name) {
|
1115
|
+
var messageName = name;
|
1116
|
+
if (this.get('portNamespace')) {
|
1117
|
+
messageName = this.get('portNamespace') + ':' + messageName;
|
1118
|
+
}
|
1119
|
+
return messageName;
|
1120
|
+
}
|
1121
|
+
});
|
1122
|
+
});
|
1123
|
+
define("models/profile_manager",
|
1124
|
+
["models/profile_node","exports"],
|
1125
|
+
function(__dependency1__, __exports__) {
|
1126
|
+
"use strict";
|
1127
|
+
var ProfileNode = __dependency1__["default"];
|
1128
|
+
var scheduleOnce = Ember.run.scheduleOnce;
|
1129
|
+
|
1130
|
+
/**
|
1131
|
+
* A class for keeping track of active rendering profiles as a list.
|
1132
|
+
*/
|
1133
|
+
var ProfileManager = function() {
|
1134
|
+
this.profiles = [];
|
1135
|
+
this.current = null;
|
1136
|
+
this.currentSet = [];
|
1137
|
+
this._profilesAddedCallbacks = [];
|
1138
|
+
};
|
1139
|
+
|
1140
|
+
ProfileManager.prototype = {
|
1141
|
+
began: function(timestamp, payload, now) {
|
1142
|
+
this.current = new ProfileNode(timestamp, payload, this.current, now);
|
1143
|
+
return this.current;
|
1144
|
+
},
|
1145
|
+
|
1146
|
+
ended: function(timestamp, payload, profileNode) {
|
1147
|
+
if (payload.exception) { throw payload.exception; }
|
1148
|
+
|
1149
|
+
this.current = profileNode.parent;
|
1150
|
+
profileNode.finish(timestamp);
|
1151
|
+
|
1152
|
+
// Are we done profiling an entire tree?
|
1153
|
+
if (!this.current) {
|
1154
|
+
this.currentSet.push(profileNode);
|
1155
|
+
// If so, schedule an update of the profile list
|
1156
|
+
scheduleOnce('afterRender', this, this._profilesFinished);
|
1157
|
+
}
|
1158
|
+
},
|
1159
|
+
|
1160
|
+
clearProfiles: function() {
|
1161
|
+
this.profiles.length = 0;
|
1162
|
+
},
|
1163
|
+
|
1164
|
+
_profilesFinished: function() {
|
1165
|
+
var firstNode = this.currentSet[0],
|
1166
|
+
parentNode = new ProfileNode(firstNode.start, {template: 'View Rendering'});
|
1167
|
+
|
1168
|
+
parentNode.time = 0;
|
1169
|
+
this.currentSet.forEach(function(n) {
|
1170
|
+
parentNode.time += n.time;
|
1171
|
+
parentNode.children.push(n);
|
1172
|
+
});
|
1173
|
+
parentNode.calcDuration();
|
1174
|
+
|
1175
|
+
this.profiles.push(parentNode);
|
1176
|
+
this._triggerProfilesAdded([parentNode]);
|
1177
|
+
this.currentSet = [];
|
1178
|
+
},
|
1179
|
+
|
1180
|
+
_profilesAddedCallbacks: undefined, // set to array on init
|
1181
|
+
|
1182
|
+
onProfilesAdded: function(context, callback) {
|
1183
|
+
this._profilesAddedCallbacks.push({
|
1184
|
+
context: context,
|
1185
|
+
callback: callback
|
1186
|
+
});
|
1187
|
+
},
|
1188
|
+
|
1189
|
+
offProfilesAdded: function(context, callback) {
|
1190
|
+
var index = -1, item;
|
1191
|
+
for (var i = 0, l = this._profilesAddedCallbacks.length; i < l; i++) {
|
1192
|
+
item = this._profilesAddedCallbacks[i];
|
1193
|
+
if (item.context === context && item.callback === callback) {
|
1194
|
+
index = i;
|
1195
|
+
}
|
1196
|
+
}
|
1197
|
+
if (index > -1) {
|
1198
|
+
this._profilesAddedCallbacks.splice(index, 1);
|
1199
|
+
}
|
1200
|
+
},
|
1201
|
+
|
1202
|
+
_triggerProfilesAdded: function(profiles) {
|
1203
|
+
this._profilesAddedCallbacks.forEach(function(item) {
|
1204
|
+
item.callback.call(item.context, profiles);
|
1205
|
+
});
|
1206
|
+
}
|
1207
|
+
};
|
1208
|
+
|
1209
|
+
__exports__["default"] = ProfileManager;
|
1210
|
+
});
|
1211
|
+
define("models/profile_node",
|
1212
|
+
["exports"],
|
1213
|
+
function(__exports__) {
|
1214
|
+
"use strict";
|
1215
|
+
/**
|
1216
|
+
A tree structure for assembling a list of render calls so they can be grouped and displayed nicely afterwards.
|
1217
|
+
|
1218
|
+
@class ProfileNode
|
1219
|
+
**/
|
1220
|
+
var get = Ember.get;
|
1221
|
+
var guidFor = Ember.guidFor;
|
1222
|
+
|
1223
|
+
var ProfileNode = function(start, payload, parent, now) {
|
1224
|
+
var name;
|
1225
|
+
this.start = start;
|
1226
|
+
this.timestamp = now || Date.now();
|
1227
|
+
|
1228
|
+
if (payload) {
|
1229
|
+
if (payload.template) {
|
1230
|
+
name = payload.template;
|
1231
|
+
} else if (payload.view) {
|
1232
|
+
var view = payload.view;
|
1233
|
+
name = get(view, 'instrumentDisplay') || get(view, '_debugContainerKey');
|
1234
|
+
if (name) {
|
1235
|
+
name = name.replace(/^view:/, '');
|
1236
|
+
}
|
1237
|
+
this.viewGuid = guidFor(view);
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
if (!name && payload.object) {
|
1241
|
+
name = payload.object.toString().replace(/:?:ember\d+>$/, '').replace(/^</, '');
|
1242
|
+
if (!this.viewGuid) {
|
1243
|
+
var match = name.match(/:(ember\d+)>$/);
|
1244
|
+
if (match && match.length > 1) {
|
1245
|
+
this.viewGuid = match[1];
|
1246
|
+
}
|
1247
|
+
}
|
1248
|
+
}
|
1249
|
+
}
|
1250
|
+
|
1251
|
+
this.name = name || 'Unknown view';
|
1252
|
+
|
1253
|
+
if (parent) { this.parent = parent; }
|
1254
|
+
this.children = [];
|
1255
|
+
};
|
1256
|
+
|
1257
|
+
ProfileNode.prototype = {
|
1258
|
+
finish: function(timestamp) {
|
1259
|
+
this.time = (timestamp - this.start);
|
1260
|
+
this.calcDuration();
|
1261
|
+
|
1262
|
+
// Once we attach to our parent, we remove that reference
|
1263
|
+
// to avoid a graph cycle when serializing:
|
1264
|
+
if (this.parent) {
|
1265
|
+
this.parent.children.push(this);
|
1266
|
+
this.parent = null;
|
1267
|
+
}
|
1268
|
+
},
|
1269
|
+
|
1270
|
+
calcDuration: function() {
|
1271
|
+
this.duration = Math.round(this.time * 100) / 100;
|
1272
|
+
}
|
1273
|
+
};
|
1274
|
+
|
1275
|
+
__exports__["default"] = ProfileNode;
|
1276
|
+
});
|
1277
|
+
define("models/promise",
|
1278
|
+
["exports"],
|
1279
|
+
function(__exports__) {
|
1280
|
+
"use strict";
|
1281
|
+
var dateComputed = function() {
|
1282
|
+
return Ember.computed(
|
1283
|
+
function(key, date) {
|
1284
|
+
if (date !== undefined) {
|
1285
|
+
if (date instanceof Date) {
|
1286
|
+
return date;
|
1287
|
+
} else if (typeof date === 'number' || typeof date === 'string') {
|
1288
|
+
return new Date(date);
|
1289
|
+
}
|
1290
|
+
}
|
1291
|
+
return null;
|
1292
|
+
}).property();
|
1293
|
+
};
|
1294
|
+
|
1295
|
+
__exports__["default"] = Ember.Object.extend({
|
1296
|
+
createdAt: dateComputed(),
|
1297
|
+
settledAt: dateComputed(),
|
1298
|
+
chainedAt: dateComputed(),
|
1299
|
+
|
1300
|
+
parent: null,
|
1301
|
+
|
1302
|
+
children: Ember.computed(function() {
|
1303
|
+
return Ember.A();
|
1304
|
+
}).property(),
|
1305
|
+
|
1306
|
+
level: Ember.computed(function() {
|
1307
|
+
var parent = this.get('parent');
|
1308
|
+
if (!parent) {
|
1309
|
+
return 0;
|
1310
|
+
}
|
1311
|
+
return parent.get('level') + 1;
|
1312
|
+
}).property('parent.level'),
|
1313
|
+
|
1314
|
+
isSettled: Ember.computed(function() {
|
1315
|
+
return this.get('isFulfilled') || this.get('isRejected');
|
1316
|
+
}).property('state'),
|
1317
|
+
|
1318
|
+
isFulfilled: Ember.computed(function() {
|
1319
|
+
return this.get('state') === 'fulfilled';
|
1320
|
+
}).property('state'),
|
1321
|
+
|
1322
|
+
isRejected: Ember.computed(function() {
|
1323
|
+
return this.get('state') === 'rejected';
|
1324
|
+
}).property('state')
|
1325
|
+
|
1326
|
+
});
|
1327
|
+
});
|
1328
|
+
define("object_inspector",
|
1329
|
+
["mixins/port_mixin","exports"],
|
1330
|
+
function(__dependency1__, __exports__) {
|
1331
|
+
"use strict";
|
1332
|
+
var PortMixin = __dependency1__["default"];
|
1333
|
+
var EmberObject = Ember.Object;
|
1334
|
+
var typeOf = Ember.typeOf;
|
1335
|
+
var Descriptor = Ember.Descriptor;
|
1336
|
+
var emberInspect = Ember.inspect;
|
1337
|
+
var computed = Ember.computed;
|
1338
|
+
var oneWay = computed.oneWay;
|
1339
|
+
var ComputedProperty = Ember.ComputedProperty;
|
1340
|
+
var get = Ember.get;
|
1341
|
+
var set = Ember.set;
|
1342
|
+
var guidFor = Ember.guidFor;
|
1343
|
+
var emberMeta = Ember.meta;
|
1344
|
+
var isNone = Ember.isNone;
|
1345
|
+
|
1346
|
+
function inspectValue(value) {
|
1347
|
+
var string;
|
1348
|
+
if (value instanceof EmberObject) {
|
1349
|
+
return { type: "type-ember-object", inspect: value.toString() };
|
1350
|
+
} else if (isComputed(value)) {
|
1351
|
+
string = "<computed>";
|
1352
|
+
return { type: "type-descriptor", inspect: string, computed: true };
|
1353
|
+
} else if (value instanceof Descriptor) {
|
1354
|
+
return { type: "type-descriptor", inspect: value.toString(), computed: true };
|
1355
|
+
} else {
|
1356
|
+
return { type: "type-" + typeOf(value), inspect: inspect(value) };
|
1357
|
+
}
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
function inspect(value) {
|
1361
|
+
if (typeof value === 'function') {
|
1362
|
+
return "function() { ... }";
|
1363
|
+
} else if (value instanceof EmberObject) {
|
1364
|
+
return value.toString();
|
1365
|
+
} else if (typeOf(value) === 'array') {
|
1366
|
+
if (value.length === 0) { return '[]'; }
|
1367
|
+
else if (value.length === 1) { return '[ ' + inspect(value[0]) + ' ]'; }
|
1368
|
+
else { return '[ ' + inspect(value[0]) + ', ... ]'; }
|
1369
|
+
} else if (value instanceof Error) {
|
1370
|
+
return 'Error: ' + value.message;
|
1371
|
+
} else if (value === null) {
|
1372
|
+
return 'null';
|
1373
|
+
} else if(typeOf(value) === 'date') {
|
1374
|
+
return value.toString();
|
1375
|
+
} else if (typeof value === 'object') {
|
1376
|
+
// `Ember.inspect` is able to handle this use case,
|
1377
|
+
// but it is very slow as it loops over all props,
|
1378
|
+
// so summarize to just first 2 props
|
1379
|
+
var ret = [], v, count = 0, broken = false;
|
1380
|
+
for (var key in value) {
|
1381
|
+
if (value.hasOwnProperty(key)) {
|
1382
|
+
if (count++ > 1) {
|
1383
|
+
broken = true;
|
1384
|
+
break;
|
1385
|
+
}
|
1386
|
+
v = value[key];
|
1387
|
+
if (v === 'toString') { continue; } // ignore useless items
|
1388
|
+
if (typeOf(v) === 'function') { v = "function() { ... }"; }
|
1389
|
+
if (typeOf(v) === 'array') { v = '[Array : ' + v.length + ']'; }
|
1390
|
+
if (typeOf(v) === 'object') { v = '[Object]'; }
|
1391
|
+
ret.push(key + ": " + v);
|
1392
|
+
}
|
1393
|
+
}
|
1394
|
+
var suffix = ' }';
|
1395
|
+
if (broken) {
|
1396
|
+
suffix = ' ...}';
|
1397
|
+
}
|
1398
|
+
return '{ ' + ret.join(', ') + suffix;
|
1399
|
+
} else {
|
1400
|
+
return emberInspect(value);
|
1401
|
+
}
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
var ObjectInspector = EmberObject.extend(PortMixin, {
|
1405
|
+
namespace: null,
|
1406
|
+
|
1407
|
+
adapter: oneWay('namespace.adapter'),
|
1408
|
+
|
1409
|
+
port: oneWay('namespace.port'),
|
1410
|
+
|
1411
|
+
application: oneWay('namespace.application'),
|
1412
|
+
|
1413
|
+
init: function() {
|
1414
|
+
this._super();
|
1415
|
+
this.set('sentObjects', {});
|
1416
|
+
this.set('boundObservers', {});
|
1417
|
+
},
|
1418
|
+
|
1419
|
+
willDestroy: function() {
|
1420
|
+
this._super();
|
1421
|
+
for (var objectId in this.sentObjects) {
|
1422
|
+
this.releaseObject(objectId);
|
1423
|
+
}
|
1424
|
+
},
|
1425
|
+
|
1426
|
+
sentObjects: {},
|
1427
|
+
|
1428
|
+
boundObservers: {},
|
1429
|
+
|
1430
|
+
portNamespace: 'objectInspector',
|
1431
|
+
|
1432
|
+
messages: {
|
1433
|
+
digDeeper: function(message) {
|
1434
|
+
this.digIntoObject(message.objectId, message.property);
|
1435
|
+
},
|
1436
|
+
releaseObject: function(message) {
|
1437
|
+
this.releaseObject(message.objectId);
|
1438
|
+
},
|
1439
|
+
calculate: function(message) {
|
1440
|
+
var value;
|
1441
|
+
value = this.valueForObjectProperty(message.objectId, message.property, message.mixinIndex);
|
1442
|
+
this.sendMessage('updateProperty', value);
|
1443
|
+
message.computed = true;
|
1444
|
+
this.bindPropertyToDebugger(message);
|
1445
|
+
},
|
1446
|
+
saveProperty: function(message) {
|
1447
|
+
this.saveProperty(message.objectId, message.mixinIndex, message.property, message.value);
|
1448
|
+
},
|
1449
|
+
sendToConsole: function(message) {
|
1450
|
+
this.sendToConsole(message.objectId, message.property);
|
1451
|
+
},
|
1452
|
+
sendControllerToConsole: function(message) {
|
1453
|
+
var container = this.get('application.__container__');
|
1454
|
+
this.sendValueToConsole(container.lookup('controller:' + message.name));
|
1455
|
+
},
|
1456
|
+
sendRouteHandlerToConsole: function(message) {
|
1457
|
+
var container = this.get('application.__container__');
|
1458
|
+
this.sendValueToConsole(container.lookup('route:' + message.name));
|
1459
|
+
},
|
1460
|
+
inspectRoute: function(message) {
|
1461
|
+
var container = this.get('application.__container__');
|
1462
|
+
this.sendObject(container.lookup('router:main').router.getHandler(message.name));
|
1463
|
+
},
|
1464
|
+
inspectController: function(message) {
|
1465
|
+
var container = this.get('application.__container__');
|
1466
|
+
this.sendObject(container.lookup('controller:' + message.name));
|
1467
|
+
},
|
1468
|
+
inspectById: function(message) {
|
1469
|
+
var obj = this.sentObjects[message.objectId];
|
1470
|
+
this.sendObject(obj);
|
1471
|
+
},
|
1472
|
+
inspectByContainerLookup: function(message) {
|
1473
|
+
var container = this.get('application.__container__');
|
1474
|
+
this.sendObject(container.lookup(message.name));
|
1475
|
+
}
|
1476
|
+
},
|
1477
|
+
|
1478
|
+
canSend: function(val) {
|
1479
|
+
return (val instanceof EmberObject) || typeOf(val) === 'array';
|
1480
|
+
},
|
1481
|
+
|
1482
|
+
saveProperty: function(objectId, mixinIndex, prop, val) {
|
1483
|
+
var object = this.sentObjects[objectId];
|
1484
|
+
set(object, prop, val);
|
1485
|
+
},
|
1486
|
+
|
1487
|
+
sendToConsole: function(objectId, prop) {
|
1488
|
+
var object = this.sentObjects[objectId];
|
1489
|
+
var value;
|
1490
|
+
|
1491
|
+
if (isNone(prop)) {
|
1492
|
+
value = this.sentObjects[objectId];
|
1493
|
+
} else {
|
1494
|
+
value = get(object, prop);
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
this.sendValueToConsole(value);
|
1498
|
+
},
|
1499
|
+
|
1500
|
+
sendValueToConsole: function(value) {
|
1501
|
+
window.$E = value;
|
1502
|
+
if (value instanceof Error) {
|
1503
|
+
value = value.stack;
|
1504
|
+
}
|
1505
|
+
this.get("adapter").log('Ember Inspector ($E): ', value);
|
1506
|
+
},
|
1507
|
+
|
1508
|
+
digIntoObject: function(objectId, property) {
|
1509
|
+
var parentObject = this.sentObjects[objectId],
|
1510
|
+
object = get(parentObject, property);
|
1511
|
+
|
1512
|
+
if (this.canSend(object)) {
|
1513
|
+
var details = this.mixinsForObject(object);
|
1514
|
+
|
1515
|
+
this.sendMessage('updateObject', {
|
1516
|
+
parentObject: objectId,
|
1517
|
+
property: property,
|
1518
|
+
objectId: details.objectId,
|
1519
|
+
name: object.toString(),
|
1520
|
+
details: details.mixins
|
1521
|
+
});
|
1522
|
+
}
|
1523
|
+
},
|
1524
|
+
|
1525
|
+
sendObject: function(object) {
|
1526
|
+
if (!this.canSend(object)) {
|
1527
|
+
throw new Error("Can't inspect " + object + ". Only Ember objects and arrays are supported.");
|
1528
|
+
}
|
1529
|
+
var details = this.mixinsForObject(object);
|
1530
|
+
this.sendMessage('updateObject', {
|
1531
|
+
objectId: details.objectId,
|
1532
|
+
name: object.toString(),
|
1533
|
+
details: details.mixins
|
1534
|
+
});
|
1535
|
+
|
1536
|
+
},
|
1537
|
+
|
1538
|
+
|
1539
|
+
retainObject: function(object) {
|
1540
|
+
var meta = emberMeta(object),
|
1541
|
+
guid = guidFor(object),
|
1542
|
+
self = this;
|
1543
|
+
|
1544
|
+
meta._debugReferences = meta._debugReferences || 0;
|
1545
|
+
meta._debugReferences++;
|
1546
|
+
|
1547
|
+
this.sentObjects[guid] = object;
|
1548
|
+
|
1549
|
+
if (meta._debugReferences === 1 && object.reopen) {
|
1550
|
+
// drop object on destruction
|
1551
|
+
var _oldWillDestroy = object._oldWillDestroy = object.willDestroy;
|
1552
|
+
object.reopen({
|
1553
|
+
willDestroy: function() {
|
1554
|
+
self.dropObject(guid);
|
1555
|
+
return _oldWillDestroy.apply(this, arguments);
|
1556
|
+
}
|
1557
|
+
});
|
1558
|
+
}
|
1559
|
+
|
1560
|
+
return guid;
|
1561
|
+
},
|
1562
|
+
|
1563
|
+
releaseObject: function(objectId) {
|
1564
|
+
var object = this.sentObjects[objectId];
|
1565
|
+
if(!object) {
|
1566
|
+
return;
|
1567
|
+
}
|
1568
|
+
var meta = emberMeta(object),
|
1569
|
+
guid = guidFor(object);
|
1570
|
+
|
1571
|
+
meta._debugReferences--;
|
1572
|
+
|
1573
|
+
if (meta._debugReferences === 0) {
|
1574
|
+
this.dropObject(guid);
|
1575
|
+
}
|
1576
|
+
|
1577
|
+
},
|
1578
|
+
|
1579
|
+
dropObject: function(objectId) {
|
1580
|
+
var object = this.sentObjects[objectId];
|
1581
|
+
|
1582
|
+
if (object.reopen) {
|
1583
|
+
object.reopen({ willDestroy: object._oldWillDestroy });
|
1584
|
+
delete object._oldWillDestroy;
|
1585
|
+
}
|
1586
|
+
|
1587
|
+
this.removeObservers(objectId);
|
1588
|
+
delete this.sentObjects[objectId];
|
1589
|
+
|
1590
|
+
this.sendMessage('droppedObject', { objectId: objectId });
|
1591
|
+
},
|
1592
|
+
|
1593
|
+
removeObservers: function(objectId) {
|
1594
|
+
var observers = this.boundObservers[objectId],
|
1595
|
+
object = this.sentObjects[objectId];
|
1596
|
+
|
1597
|
+
if (observers) {
|
1598
|
+
observers.forEach(function(observer) {
|
1599
|
+
Ember.removeObserver(object, observer.property, observer.handler);
|
1600
|
+
});
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
delete this.boundObservers[objectId];
|
1604
|
+
},
|
1605
|
+
|
1606
|
+
mixinsForObject: function(object) {
|
1607
|
+
var mixins = Ember.Mixin.mixins(object),
|
1608
|
+
mixinDetails = [],
|
1609
|
+
self = this;
|
1610
|
+
|
1611
|
+
var ownProps = propertiesForMixin({ mixins: [{ properties: object }] });
|
1612
|
+
mixinDetails.push({ name: "Own Properties", properties: ownProps, expand: true });
|
1613
|
+
|
1614
|
+
mixins.forEach(function(mixin) {
|
1615
|
+
var name = mixin[Ember.NAME_KEY] || mixin.ownerConstructor;
|
1616
|
+
if (!name) {
|
1617
|
+
name = 'Unknown mixin';
|
1618
|
+
}
|
1619
|
+
mixinDetails.push({ name: name.toString(), properties: propertiesForMixin(mixin) });
|
1620
|
+
});
|
1621
|
+
|
1622
|
+
fixMandatorySetters(mixinDetails);
|
1623
|
+
applyMixinOverrides(mixinDetails);
|
1624
|
+
|
1625
|
+
var propertyInfo = null;
|
1626
|
+
var debugInfo = getDebugInfo(object);
|
1627
|
+
if (debugInfo) {
|
1628
|
+
propertyInfo = getDebugInfo(object).propertyInfo;
|
1629
|
+
mixinDetails = customizeProperties(mixinDetails, propertyInfo);
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
var expensiveProperties = null;
|
1633
|
+
if (propertyInfo) {
|
1634
|
+
expensiveProperties = propertyInfo.expensiveProperties;
|
1635
|
+
}
|
1636
|
+
calculateCPs(object, mixinDetails, expensiveProperties);
|
1637
|
+
|
1638
|
+
var objectId = this.retainObject(object);
|
1639
|
+
|
1640
|
+
this.bindProperties(objectId, mixinDetails);
|
1641
|
+
|
1642
|
+
return { objectId: objectId, mixins: mixinDetails };
|
1643
|
+
},
|
1644
|
+
|
1645
|
+
valueForObjectProperty: function(objectId, property, mixinIndex) {
|
1646
|
+
var object = this.sentObjects[objectId], value;
|
1647
|
+
|
1648
|
+
if (object.isDestroying) {
|
1649
|
+
value = '<DESTROYED>';
|
1650
|
+
} else {
|
1651
|
+
value = object.get(property);
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
value = inspectValue(value);
|
1655
|
+
value.computed = true;
|
1656
|
+
|
1657
|
+
return {
|
1658
|
+
objectId: objectId,
|
1659
|
+
property: property,
|
1660
|
+
value: value,
|
1661
|
+
mixinIndex: mixinIndex
|
1662
|
+
};
|
1663
|
+
},
|
1664
|
+
|
1665
|
+
bindPropertyToDebugger: function(message) {
|
1666
|
+
var objectId = message.objectId,
|
1667
|
+
property = message.property,
|
1668
|
+
mixinIndex = message.mixinIndex,
|
1669
|
+
computed = message.computed,
|
1670
|
+
self = this;
|
1671
|
+
|
1672
|
+
var object = this.sentObjects[objectId];
|
1673
|
+
|
1674
|
+
function handler() {
|
1675
|
+
var value = get(object, property);
|
1676
|
+
value = inspectValue(value);
|
1677
|
+
value.computed = computed;
|
1678
|
+
|
1679
|
+
self.sendMessage('updateProperty', {
|
1680
|
+
objectId: objectId,
|
1681
|
+
property: property,
|
1682
|
+
value: value,
|
1683
|
+
mixinIndex: mixinIndex
|
1684
|
+
});
|
1685
|
+
}
|
1686
|
+
|
1687
|
+
Ember.addObserver(object, property, handler);
|
1688
|
+
this.boundObservers[objectId] = this.boundObservers[objectId] || [];
|
1689
|
+
this.boundObservers[objectId].push({ property: property, handler: handler });
|
1690
|
+
|
1691
|
+
},
|
1692
|
+
|
1693
|
+
bindProperties: function(objectId, mixinDetails) {
|
1694
|
+
var self = this;
|
1695
|
+
mixinDetails.forEach(function(mixin, mixinIndex) {
|
1696
|
+
mixin.properties.forEach(function(item) {
|
1697
|
+
if (item.overridden) {
|
1698
|
+
return true;
|
1699
|
+
}
|
1700
|
+
if (item.value.type !== 'type-descriptor' && item.value.type !== 'type-function') {
|
1701
|
+
var computed = !!item.value.computed;
|
1702
|
+
self.bindPropertyToDebugger({
|
1703
|
+
objectId: objectId,
|
1704
|
+
property: item.name,
|
1705
|
+
mixinIndex: mixinIndex,
|
1706
|
+
computed: computed
|
1707
|
+
});
|
1708
|
+
}
|
1709
|
+
});
|
1710
|
+
});
|
1711
|
+
},
|
1712
|
+
|
1713
|
+
inspect: inspect,
|
1714
|
+
inspectValue: inspectValue
|
1715
|
+
});
|
1716
|
+
|
1717
|
+
|
1718
|
+
function propertiesForMixin(mixin) {
|
1719
|
+
var seen = {}, properties = [];
|
1720
|
+
|
1721
|
+
mixin.mixins.forEach(function(mixin) {
|
1722
|
+
if (mixin.properties) {
|
1723
|
+
addProperties(properties, mixin.properties);
|
1724
|
+
}
|
1725
|
+
});
|
1726
|
+
|
1727
|
+
return properties;
|
1728
|
+
}
|
1729
|
+
|
1730
|
+
function addProperties(properties, hash) {
|
1731
|
+
for (var prop in hash) {
|
1732
|
+
if (!hash.hasOwnProperty(prop)) { continue; }
|
1733
|
+
if (prop.charAt(0) === '_') { continue; }
|
1734
|
+
|
1735
|
+
// remove `fooBinding` type props
|
1736
|
+
if (prop.match(/Binding$/)) { continue; }
|
1737
|
+
|
1738
|
+
// when mandatory setter is removed, an `undefined` value may be set
|
1739
|
+
if (hash[prop] === undefined) { continue; }
|
1740
|
+
var options = { isMandatorySetter: isMandatorySetter(hash, prop) };
|
1741
|
+
if (isComputed(hash[prop])) {
|
1742
|
+
options.readOnly = hash[prop]._readOnly;
|
1743
|
+
}
|
1744
|
+
replaceProperty(properties, prop, hash[prop], options);
|
1745
|
+
}
|
1746
|
+
}
|
1747
|
+
|
1748
|
+
function replaceProperty(properties, name, value, options) {
|
1749
|
+
var found, type;
|
1750
|
+
|
1751
|
+
for (var i=0, l=properties.length; i<l; i++) {
|
1752
|
+
if (properties[i].name === name) {
|
1753
|
+
found = i;
|
1754
|
+
break;
|
1755
|
+
}
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
if (found) { properties.splice(i, 1); }
|
1759
|
+
|
1760
|
+
if (name) {
|
1761
|
+
type = name.PrototypeMixin ? 'ember-class' : 'ember-mixin';
|
1762
|
+
}
|
1763
|
+
var prop = { name: name, value: inspectValue(value) };
|
1764
|
+
prop.isMandatorySetter = options.isMandatorySetter;
|
1765
|
+
prop.readOnly = options.readOnly;
|
1766
|
+
properties.push(prop);
|
1767
|
+
}
|
1768
|
+
|
1769
|
+
function fixMandatorySetters(mixinDetails) {
|
1770
|
+
var seen = {};
|
1771
|
+
var propertiesToRemove = [];
|
1772
|
+
|
1773
|
+
mixinDetails.forEach(function(detail, detailIdx) {
|
1774
|
+
detail.properties.forEach(function(property, propertyIdx) {
|
1775
|
+
if(property.isMandatorySetter) {
|
1776
|
+
seen[property.name] = {
|
1777
|
+
name: property.name,
|
1778
|
+
value: property.value.inspect,
|
1779
|
+
detailIdx: detailIdx,
|
1780
|
+
property: property
|
1781
|
+
};
|
1782
|
+
} else if(seen.hasOwnProperty(property.name) && seen[property.name] === property.value.inspect) {
|
1783
|
+
propertiesToRemove.push(seen[property.name]);
|
1784
|
+
delete seen[property.name];
|
1785
|
+
}
|
1786
|
+
});
|
1787
|
+
});
|
1788
|
+
|
1789
|
+
propertiesToRemove.forEach(function(prop) {
|
1790
|
+
var detail = mixinDetails[prop.detailIdx];
|
1791
|
+
var index = detail.properties.indexOf(prop.property);
|
1792
|
+
if (index !== -1) {
|
1793
|
+
detail.properties.splice(index, 1);
|
1794
|
+
}
|
1795
|
+
});
|
1796
|
+
|
1797
|
+
}
|
1798
|
+
|
1799
|
+
function applyMixinOverrides(mixinDetails) {
|
1800
|
+
var seen = {};
|
1801
|
+
mixinDetails.forEach(function(detail) {
|
1802
|
+
detail.properties.forEach(function(property) {
|
1803
|
+
if (Object.prototype.hasOwnProperty(property.name)) { return; }
|
1804
|
+
|
1805
|
+
if (seen[property.name]) {
|
1806
|
+
property.overridden = seen[property.name];
|
1807
|
+
delete property.value.computed;
|
1808
|
+
}
|
1809
|
+
|
1810
|
+
seen[property.name] = detail.name;
|
1811
|
+
|
1812
|
+
});
|
1813
|
+
});
|
1814
|
+
}
|
1815
|
+
|
1816
|
+
function isMandatorySetter(object, prop) {
|
1817
|
+
var descriptor = Object.getOwnPropertyDescriptor(object, prop);
|
1818
|
+
if (descriptor.set && descriptor.set === Ember.MANDATORY_SETTER_FUNCTION) {
|
1819
|
+
return true;
|
1820
|
+
}
|
1821
|
+
return false;
|
1822
|
+
}
|
1823
|
+
|
1824
|
+
|
1825
|
+
|
1826
|
+
|
1827
|
+
|
1828
|
+
|
1829
|
+
function calculateCPs(object, mixinDetails, expensiveProperties) {
|
1830
|
+
expensiveProperties = expensiveProperties || [];
|
1831
|
+
|
1832
|
+
mixinDetails.forEach(function(mixin) {
|
1833
|
+
mixin.properties.forEach(function(item) {
|
1834
|
+
if (item.overridden) {
|
1835
|
+
return true;
|
1836
|
+
}
|
1837
|
+
if (item.value.computed) {
|
1838
|
+
var cache = Ember.cacheFor(object, item.name);
|
1839
|
+
if (cache !== undefined || expensiveProperties.indexOf(item.name) === -1) {
|
1840
|
+
item.value = inspectValue(get(object, item.name));
|
1841
|
+
item.value.computed = true;
|
1842
|
+
}
|
1843
|
+
}
|
1844
|
+
});
|
1845
|
+
});
|
1846
|
+
}
|
1847
|
+
|
1848
|
+
/**
|
1849
|
+
Customizes an object's properties
|
1850
|
+
based on the property `propertyInfo` of
|
1851
|
+
the object's `_debugInfo` method.
|
1852
|
+
|
1853
|
+
Possible options:
|
1854
|
+
- `groups` An array of groups that contains the properties for each group
|
1855
|
+
For example:
|
1856
|
+
```javascript
|
1857
|
+
groups: [
|
1858
|
+
{ name: 'Attributes', properties: ['firstName', 'lastName'] },
|
1859
|
+
{ name: 'Belongs To', properties: ['country'] }
|
1860
|
+
]
|
1861
|
+
```
|
1862
|
+
- `includeOtherProperties` Boolean,
|
1863
|
+
- `true` to include other non-listed properties,
|
1864
|
+
- `false` to only include given properties
|
1865
|
+
- `skipProperties` Array containing list of properties *not* to include
|
1866
|
+
- `skipMixins` Array containing list of mixins *not* to include
|
1867
|
+
- `expensiveProperties` An array of computed properties that are too expensive.
|
1868
|
+
Adding a property to this array makes sure the CP is not calculated automatically.
|
1869
|
+
|
1870
|
+
Example:
|
1871
|
+
```javascript
|
1872
|
+
{
|
1873
|
+
propertyInfo: {
|
1874
|
+
includeOtherProperties: true,
|
1875
|
+
skipProperties: ['toString', 'send', 'withTransaction'],
|
1876
|
+
skipMixins: [ 'Ember.Evented'],
|
1877
|
+
calculate: ['firstName', 'lastName'],
|
1878
|
+
groups: [
|
1879
|
+
{
|
1880
|
+
name: 'Attributes',
|
1881
|
+
properties: [ 'id', 'firstName', 'lastName' ],
|
1882
|
+
expand: true // open by default
|
1883
|
+
},
|
1884
|
+
{
|
1885
|
+
name: 'Belongs To',
|
1886
|
+
properties: [ 'maritalStatus', 'avatar' ],
|
1887
|
+
expand: true
|
1888
|
+
},
|
1889
|
+
{
|
1890
|
+
name: 'Has Many',
|
1891
|
+
properties: [ 'phoneNumbers' ],
|
1892
|
+
expand: true
|
1893
|
+
},
|
1894
|
+
{
|
1895
|
+
name: 'Flags',
|
1896
|
+
properties: ['isLoaded', 'isLoading', 'isNew', 'isDirty']
|
1897
|
+
}
|
1898
|
+
]
|
1899
|
+
}
|
1900
|
+
}
|
1901
|
+
```
|
1902
|
+
*/
|
1903
|
+
function customizeProperties(mixinDetails, propertyInfo) {
|
1904
|
+
var newMixinDetails = [],
|
1905
|
+
neededProperties = {},
|
1906
|
+
groups = propertyInfo.groups || [],
|
1907
|
+
skipProperties = propertyInfo.skipProperties || [],
|
1908
|
+
skipMixins = propertyInfo.skipMixins || [];
|
1909
|
+
|
1910
|
+
if(groups.length) {
|
1911
|
+
mixinDetails[0].expand = false;
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
groups.forEach(function(group) {
|
1915
|
+
group.properties.forEach(function(prop) {
|
1916
|
+
neededProperties[prop] = true;
|
1917
|
+
});
|
1918
|
+
});
|
1919
|
+
|
1920
|
+
mixinDetails.forEach(function(mixin) {
|
1921
|
+
var newProperties = [];
|
1922
|
+
mixin.properties.forEach(function(item) {
|
1923
|
+
if (skipProperties.indexOf(item.name) !== -1) {
|
1924
|
+
return true;
|
1925
|
+
}
|
1926
|
+
if (!item.overridden && neededProperties.hasOwnProperty(item.name) && neededProperties[item.name]) {
|
1927
|
+
neededProperties[item.name] = item;
|
1928
|
+
} else {
|
1929
|
+
newProperties.push(item);
|
1930
|
+
}
|
1931
|
+
});
|
1932
|
+
mixin.properties = newProperties;
|
1933
|
+
if (skipMixins.indexOf(mixin.name) === -1) {
|
1934
|
+
newMixinDetails.push(mixin);
|
1935
|
+
}
|
1936
|
+
});
|
1937
|
+
|
1938
|
+
groups.slice().reverse().forEach(function(group) {
|
1939
|
+
var newMixin = { name: group.name, expand: group.expand, properties: [] };
|
1940
|
+
group.properties.forEach(function(prop) {
|
1941
|
+
// make sure it's not `true` which means property wasn't found
|
1942
|
+
if (neededProperties[prop] !== true) {
|
1943
|
+
newMixin.properties.push(neededProperties[prop]);
|
1944
|
+
}
|
1945
|
+
});
|
1946
|
+
newMixinDetails.unshift(newMixin);
|
1947
|
+
});
|
1948
|
+
|
1949
|
+
return newMixinDetails;
|
1950
|
+
}
|
1951
|
+
|
1952
|
+
|
1953
|
+
function getDebugInfo(object) {
|
1954
|
+
var debugInfo = null;
|
1955
|
+
if (object._debugInfo && typeof object._debugInfo === 'function') {
|
1956
|
+
debugInfo = object._debugInfo();
|
1957
|
+
}
|
1958
|
+
debugInfo = debugInfo || {};
|
1959
|
+
var propertyInfo = debugInfo.propertyInfo || (debugInfo.propertyInfo = {});
|
1960
|
+
var skipProperties = propertyInfo.skipProperties = propertyInfo.skipProperties || (propertyInfo.skipProperties = []);
|
1961
|
+
|
1962
|
+
skipProperties.push('isDestroyed', 'isDestroying', 'container');
|
1963
|
+
// 'currentState' and 'state' are un-observable private properties.
|
1964
|
+
// The rest are skipped to reduce noise in the inspector.
|
1965
|
+
if (object instanceof Ember.View) {
|
1966
|
+
skipProperties.push(
|
1967
|
+
'currentState',
|
1968
|
+
'state',
|
1969
|
+
'buffer',
|
1970
|
+
'outletSource',
|
1971
|
+
'lengthBeforeRender',
|
1972
|
+
'lengthAfterRender',
|
1973
|
+
'template',
|
1974
|
+
'layout',
|
1975
|
+
'templateData',
|
1976
|
+
'domManager',
|
1977
|
+
'states'
|
1978
|
+
);
|
1979
|
+
}
|
1980
|
+
|
1981
|
+
|
1982
|
+
for (var prop in object) {
|
1983
|
+
// remove methods
|
1984
|
+
if (typeof object[prop] === 'function') {
|
1985
|
+
skipProperties.push(prop);
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
}
|
1989
|
+
return debugInfo;
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
function isComputed(value) {
|
1993
|
+
return value instanceof ComputedProperty;
|
1994
|
+
}
|
1995
|
+
|
1996
|
+
// Not used
|
1997
|
+
function inspectController(controller) {
|
1998
|
+
return controller.get('_debugContainerKey') || controller.toString();
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
__exports__["default"] = ObjectInspector;
|
2002
|
+
});
|
2003
|
+
define("port",
|
2004
|
+
["exports"],
|
2005
|
+
function(__exports__) {
|
2006
|
+
"use strict";
|
2007
|
+
var oneWay = Ember.computed.oneWay;
|
2008
|
+
var guidFor = Ember.guidFor;
|
2009
|
+
|
2010
|
+
__exports__["default"] = Ember.Object.extend(Ember.Evented, {
|
2011
|
+
adapter: oneWay('namespace.adapter').readOnly(),
|
2012
|
+
|
2013
|
+
application: oneWay('namespace.application').readOnly(),
|
2014
|
+
|
2015
|
+
uniqueId: Ember.computed(function() {
|
2016
|
+
return guidFor(this.get('application')) + '__' + window.location.href + '__' + Date.now();
|
2017
|
+
}).property(),
|
2018
|
+
|
2019
|
+
init: function() {
|
2020
|
+
var self = this;
|
2021
|
+
this.get('adapter').onMessageReceived(function(message) {
|
2022
|
+
if(self.get('uniqueId') === message.applicationId || !message.applicationId) {
|
2023
|
+
self.trigger(message.type, message);
|
2024
|
+
}
|
2025
|
+
});
|
2026
|
+
},
|
2027
|
+
send: function(messageType, options) {
|
2028
|
+
options.type = messageType;
|
2029
|
+
options.from = 'inspectedWindow';
|
2030
|
+
options.applicationId = this.get('uniqueId');
|
2031
|
+
this.get('adapter').sendMessage(options);
|
2032
|
+
}
|
2033
|
+
});
|
2034
|
+
});
|
2035
|
+
define("promise_debug",
|
2036
|
+
["mixins/port_mixin","libs/promise_assembler","exports"],
|
2037
|
+
function(__dependency1__, __dependency2__, __exports__) {
|
2038
|
+
"use strict";
|
2039
|
+
var PortMixin = __dependency1__["default"];
|
2040
|
+
var PromiseAssembler = __dependency2__["default"];
|
2041
|
+
|
2042
|
+
var PromiseDebug = Ember.Object.extend(PortMixin, {
|
2043
|
+
namespace: null,
|
2044
|
+
port: Ember.computed.alias('namespace.port'),
|
2045
|
+
objectInspector: Ember.computed.alias('namespace.objectInspector'),
|
2046
|
+
adapter: Ember.computed.alias('namespace.adapter'),
|
2047
|
+
portNamespace: 'promise',
|
2048
|
+
|
2049
|
+
|
2050
|
+
existingEvents: Ember.computed.alias('namespace.existingEvents'),
|
2051
|
+
existingCallbacks: Ember.computed.alias('namespace.existingCallbacks'),
|
2052
|
+
|
2053
|
+
// created on init
|
2054
|
+
promiseAssembler: null,
|
2055
|
+
|
2056
|
+
releaseMethods: Ember.computed(function() { return Ember.A(); }),
|
2057
|
+
|
2058
|
+
init: function() {
|
2059
|
+
this._super();
|
2060
|
+
if (PromiseAssembler.supported()) {
|
2061
|
+
this.set('promiseAssembler', PromiseAssembler.create());
|
2062
|
+
this.get('promiseAssembler').set('promiseDebug', this);
|
2063
|
+
this.get('promiseAssembler').start();
|
2064
|
+
}
|
2065
|
+
},
|
2066
|
+
|
2067
|
+
delay: 100,
|
2068
|
+
|
2069
|
+
willDestroy: function() {
|
2070
|
+
this.releaseAll();
|
2071
|
+
this.get('promiseAssembler').destroy();
|
2072
|
+
this.set('promiseAssembler', null);
|
2073
|
+
this._super();
|
2074
|
+
},
|
2075
|
+
|
2076
|
+
messages: {
|
2077
|
+
getAndObservePromises: function() {
|
2078
|
+
this.getAndObservePromises();
|
2079
|
+
},
|
2080
|
+
|
2081
|
+
supported: function() {
|
2082
|
+
this.sendMessage('supported', {
|
2083
|
+
supported: PromiseAssembler.supported()
|
2084
|
+
});
|
2085
|
+
},
|
2086
|
+
|
2087
|
+
releasePromises: function() {
|
2088
|
+
this.releaseAll();
|
2089
|
+
},
|
2090
|
+
|
2091
|
+
sendValueToConsole: function(message) {
|
2092
|
+
var promiseId = message.promiseId;
|
2093
|
+
var promise = this.get('promiseAssembler').find(promiseId);
|
2094
|
+
var value = promise.get('value');
|
2095
|
+
if (value === undefined) {
|
2096
|
+
value = promise.get('reason');
|
2097
|
+
}
|
2098
|
+
this.get('objectInspector').sendValueToConsole(value);
|
2099
|
+
},
|
2100
|
+
|
2101
|
+
tracePromise: function(message) {
|
2102
|
+
var id = message.promiseId;
|
2103
|
+
var promise = this.get('promiseAssembler').find(id);
|
2104
|
+
// Remove first two lines and add label
|
2105
|
+
var stack = promise.get('stack');
|
2106
|
+
if (stack) {
|
2107
|
+
stack = stack.split("\n");
|
2108
|
+
stack.splice(0, 2, ['Ember Inspector (Promise Trace): ' + (promise.get('label') || '')]);
|
2109
|
+
this.get("adapter").log(stack.join("\n"));
|
2110
|
+
}
|
2111
|
+
},
|
2112
|
+
|
2113
|
+
setInstrumentWithStack: function(message) {
|
2114
|
+
Ember.RSVP.configure('instrument-with-stack', message.instrumentWithStack);
|
2115
|
+
}
|
2116
|
+
},
|
2117
|
+
|
2118
|
+
releaseAll: function() {
|
2119
|
+
this.get('releaseMethods').forEach(function(fn) {
|
2120
|
+
fn();
|
2121
|
+
});
|
2122
|
+
this.set('releaseMethods', Ember.A());
|
2123
|
+
},
|
2124
|
+
|
2125
|
+
getAndObservePromises: function() {
|
2126
|
+
this.get('promiseAssembler').on('created', this, this.promiseUpdated);
|
2127
|
+
this.get('promiseAssembler').on('fulfilled', this, this.promiseUpdated);
|
2128
|
+
this.get('promiseAssembler').on('rejected', this, this.promiseUpdated);
|
2129
|
+
this.get('promiseAssembler').on('chained', this, this.promiseChained);
|
2130
|
+
|
2131
|
+
this.get('releaseMethods').pushObject(function() {
|
2132
|
+
|
2133
|
+
this.get('promiseAssembler').off('created', this, this.promiseUpdated);
|
2134
|
+
this.get('promiseAssembler').off('fulfilled', this, this.promiseUpdated);
|
2135
|
+
this.get('promiseAssembler').off('rejected', this, this.promiseUpdated);
|
2136
|
+
this.get('promiseAssembler').off('fulfilled', this, this.promiseChained);
|
2137
|
+
|
2138
|
+
}.bind(this));
|
2139
|
+
|
2140
|
+
this.promisesUpdated(this.get('promiseAssembler').find());
|
2141
|
+
},
|
2142
|
+
|
2143
|
+
updatedPromises: Ember.computed(function() { return Ember.A(); }),
|
2144
|
+
|
2145
|
+
promisesUpdated: function(uniquePromises) {
|
2146
|
+
if (!uniquePromises) {
|
2147
|
+
uniquePromises = Ember.A();
|
2148
|
+
this.get('updatedPromises').forEach(function(promise) {
|
2149
|
+
uniquePromises.addObject(promise);
|
2150
|
+
});
|
2151
|
+
}
|
2152
|
+
var serialized = this.serializeArray(uniquePromises);
|
2153
|
+
this.sendMessage('promisesUpdated', {
|
2154
|
+
promises: serialized
|
2155
|
+
});
|
2156
|
+
this.set('updatedPromises', Ember.A());
|
2157
|
+
},
|
2158
|
+
|
2159
|
+
promiseUpdated: function(event) {
|
2160
|
+
this.get('updatedPromises').pushObject(event.promise);
|
2161
|
+
Ember.run.debounce(this, 'promisesUpdated', this.delay);
|
2162
|
+
},
|
2163
|
+
|
2164
|
+
promiseChained: function(event) {
|
2165
|
+
this.get('updatedPromises').pushObject(event.promise);
|
2166
|
+
this.get('updatedPromises').pushObject(event.child);
|
2167
|
+
Ember.run.debounce(this, 'promisesUpdated', this.delay);
|
2168
|
+
},
|
2169
|
+
|
2170
|
+
serializeArray: function(promises) {
|
2171
|
+
return promises.map(function(item) {
|
2172
|
+
return this.serialize(item);
|
2173
|
+
}.bind(this));
|
2174
|
+
},
|
2175
|
+
|
2176
|
+
serialize: function(promise) {
|
2177
|
+
var serialized = {};
|
2178
|
+
serialized.guid = promise.get('guid');
|
2179
|
+
serialized.state = promise.get('state');
|
2180
|
+
serialized.label = promise.get('label');
|
2181
|
+
if (promise.get('children')) {
|
2182
|
+
serialized.children = this.promiseIds(promise.get('children'));
|
2183
|
+
}
|
2184
|
+
serialized.parent = promise.get('parent.guid');
|
2185
|
+
serialized.value = this.inspectValue(promise.get('value'));
|
2186
|
+
serialized.reason = this.inspectValue(promise.get('reason'));
|
2187
|
+
if (promise.get('createdAt')) {
|
2188
|
+
serialized.createdAt = promise.get('createdAt').getTime();
|
2189
|
+
}
|
2190
|
+
if (promise.get('settledAt')) {
|
2191
|
+
serialized.settledAt = promise.get('settledAt').getTime();
|
2192
|
+
}
|
2193
|
+
serialized.hasStack = !!promise.get('stack');
|
2194
|
+
return serialized;
|
2195
|
+
},
|
2196
|
+
|
2197
|
+
promiseIds: function(promises) {
|
2198
|
+
return promises.map(function(promise) {
|
2199
|
+
return promise.get('guid');
|
2200
|
+
});
|
2201
|
+
},
|
2202
|
+
|
2203
|
+
inspectValue: function(value) {
|
2204
|
+
var objectInspector = this.get('objectInspector'),
|
2205
|
+
inspected = objectInspector.inspectValue(value);
|
2206
|
+
|
2207
|
+
if (inspected.type === 'type-ember-object' || inspected.type === "type-array") {
|
2208
|
+
inspected.objectId = objectInspector.retainObject(value);
|
2209
|
+
this.get('releaseMethods').pushObject(function() {
|
2210
|
+
objectInspector.releaseObject(inspected.objectId);
|
2211
|
+
});
|
2212
|
+
}
|
2213
|
+
return inspected;
|
2214
|
+
}
|
2215
|
+
|
2216
|
+
});
|
2217
|
+
|
2218
|
+
__exports__["default"] = PromiseDebug;
|
2219
|
+
});
|
2220
|
+
define("render_debug",
|
2221
|
+
["mixins/port_mixin","models/profile_manager","exports"],
|
2222
|
+
function(__dependency1__, __dependency2__, __exports__) {
|
2223
|
+
"use strict";
|
2224
|
+
var PortMixin = __dependency1__["default"];
|
2225
|
+
var ProfileManager = __dependency2__["default"];
|
2226
|
+
|
2227
|
+
var K = Ember.K;
|
2228
|
+
var addArrayObserver = Ember.addArrayObserver;
|
2229
|
+
var computed = Ember.computed;
|
2230
|
+
var oneWay = computed.oneWay;
|
2231
|
+
var later = Ember.run.later;
|
2232
|
+
|
2233
|
+
var profileManager = new ProfileManager();
|
2234
|
+
|
2235
|
+
var queue = [];
|
2236
|
+
|
2237
|
+
function push(info) {
|
2238
|
+
var index = queue.push(info);
|
2239
|
+
if (1 === index) {
|
2240
|
+
later(flush, 50);
|
2241
|
+
}
|
2242
|
+
return index - 1;
|
2243
|
+
}
|
2244
|
+
|
2245
|
+
function flush() {
|
2246
|
+
var entry, ended, i;
|
2247
|
+
for (i = 0; i < queue.length; i++) {
|
2248
|
+
entry = queue[i];
|
2249
|
+
if (entry.type === 'began') {
|
2250
|
+
queue[entry.endedIndex].profileNode = profileManager.began(entry.timestamp, entry.payload, entry.now);
|
2251
|
+
} else {
|
2252
|
+
profileManager.ended(entry.timestamp, entry.payload, entry.profileNode);
|
2253
|
+
}
|
2254
|
+
|
2255
|
+
}
|
2256
|
+
queue.length = 0;
|
2257
|
+
}
|
2258
|
+
|
2259
|
+
Ember.subscribe("render", {
|
2260
|
+
before: function(name, timestamp, payload) {
|
2261
|
+
var info = {
|
2262
|
+
type: 'began',
|
2263
|
+
timestamp: timestamp,
|
2264
|
+
payload: payload,
|
2265
|
+
now: Date.now()
|
2266
|
+
};
|
2267
|
+
return push(info);
|
2268
|
+
},
|
2269
|
+
|
2270
|
+
after: function(name, timestamp, payload, beganIndex) {
|
2271
|
+
var endedInfo = {
|
2272
|
+
type: 'ended',
|
2273
|
+
timestamp: timestamp,
|
2274
|
+
payload: payload
|
2275
|
+
};
|
2276
|
+
|
2277
|
+
var index = push(endedInfo);
|
2278
|
+
queue[beganIndex].endedIndex = index;
|
2279
|
+
}
|
2280
|
+
});
|
2281
|
+
|
2282
|
+
__exports__["default"] = Ember.Object.extend(PortMixin, {
|
2283
|
+
namespace: null,
|
2284
|
+
port: oneWay('namespace.port').readOnly(),
|
2285
|
+
application: oneWay('namespace.application').readOnly(),
|
2286
|
+
viewDebug: oneWay('namespace.viewDebug').readOnly(),
|
2287
|
+
portNamespace: 'render',
|
2288
|
+
|
2289
|
+
profileManager: profileManager,
|
2290
|
+
|
2291
|
+
init: function() {
|
2292
|
+
this._super();
|
2293
|
+
this._subscribeForViewTrees();
|
2294
|
+
},
|
2295
|
+
|
2296
|
+
willDestroy: function() {
|
2297
|
+
this._super();
|
2298
|
+
this.profileManager.offProfilesAdded(this, this.sendAdded);
|
2299
|
+
this.profileManager.offProfilesAdded(this, this._updateViewTree);
|
2300
|
+
},
|
2301
|
+
|
2302
|
+
_subscribeForViewTrees: function() {
|
2303
|
+
this.profileManager.onProfilesAdded(this, this._updateViewTree);
|
2304
|
+
},
|
2305
|
+
|
2306
|
+
_updateViewTree: function(profiles) {
|
2307
|
+
var viewDurations = {};
|
2308
|
+
this._flatten(profiles).forEach(function(node) {
|
2309
|
+
if (node.viewGuid) {
|
2310
|
+
viewDurations[node.viewGuid] = node.duration;
|
2311
|
+
}
|
2312
|
+
});
|
2313
|
+
this.get('viewDebug').updateDurations(viewDurations);
|
2314
|
+
},
|
2315
|
+
|
2316
|
+
_flatten: function(profiles, array) {
|
2317
|
+
var self = this;
|
2318
|
+
array = array || [];
|
2319
|
+
profiles.forEach(function(profile) {
|
2320
|
+
array.push(profile);
|
2321
|
+
self._flatten(profile.children, array);
|
2322
|
+
});
|
2323
|
+
return array;
|
2324
|
+
},
|
2325
|
+
|
2326
|
+
sendAdded: function(profiles) {
|
2327
|
+
this.sendMessage('profilesAdded', { profiles: profiles });
|
2328
|
+
},
|
2329
|
+
|
2330
|
+
messages: {
|
2331
|
+
watchProfiles: function() {
|
2332
|
+
this.sendMessage('profilesAdded', { profiles: this.profileManager.profiles });
|
2333
|
+
this.profileManager.onProfilesAdded(this, this.sendAdded);
|
2334
|
+
},
|
2335
|
+
|
2336
|
+
releaseProfiles: function() {
|
2337
|
+
this.profileManager.offProfilesAdded(this, this.sendAdded);
|
2338
|
+
},
|
2339
|
+
|
2340
|
+
clear: function() {
|
2341
|
+
this.profileManager.clearProfiles();
|
2342
|
+
this.sendMessage('profilesUpdated', {profiles: []});
|
2343
|
+
}
|
2344
|
+
}
|
2345
|
+
});
|
2346
|
+
});
|
2347
|
+
define("route_debug",
|
2348
|
+
["mixins/port_mixin","exports"],
|
2349
|
+
function(__dependency1__, __exports__) {
|
2350
|
+
"use strict";
|
2351
|
+
var PortMixin = __dependency1__["default"];
|
2352
|
+
|
2353
|
+
var classify = Ember.String.classify;
|
2354
|
+
var computed = Ember.computed;
|
2355
|
+
var oneWay = computed.oneWay;
|
2356
|
+
var observer = Ember.observer;
|
2357
|
+
var later = Ember.run.later;
|
2358
|
+
|
2359
|
+
var RouteDebug = Ember.Object.extend(PortMixin, {
|
2360
|
+
namespace: null,
|
2361
|
+
port: oneWay('namespace.port').readOnly(),
|
2362
|
+
|
2363
|
+
application: oneWay('namespace.application').readOnly(),
|
2364
|
+
|
2365
|
+
router: computed(function() {
|
2366
|
+
return this.get('application.__container__').lookup('router:main');
|
2367
|
+
}).property('application'),
|
2368
|
+
|
2369
|
+
applicationController: computed(function() {
|
2370
|
+
var container = this.get('application.__container__');
|
2371
|
+
return container.lookup('controller:application');
|
2372
|
+
}).property('application'),
|
2373
|
+
|
2374
|
+
currentPath: oneWay('applicationController.currentPath').readOnly(),
|
2375
|
+
|
2376
|
+
portNamespace: 'route',
|
2377
|
+
|
2378
|
+
messages: {
|
2379
|
+
getTree: function() {
|
2380
|
+
this.sendTree();
|
2381
|
+
},
|
2382
|
+
getCurrentRoute: function() {
|
2383
|
+
this.sendCurrentRoute();
|
2384
|
+
}
|
2385
|
+
},
|
2386
|
+
|
2387
|
+
sendCurrentRoute: observer(function() {
|
2388
|
+
var self = this;
|
2389
|
+
later(function() {
|
2390
|
+
self.sendMessage('currentRoute', { name: self.get('currentPath') });
|
2391
|
+
}, 50);
|
2392
|
+
}, 'currentPath'),
|
2393
|
+
|
2394
|
+
routeTree: computed(function() {
|
2395
|
+
var routeNames = this.get('router.router.recognizer.names');
|
2396
|
+
var routeTree = {};
|
2397
|
+
|
2398
|
+
for(var routeName in routeNames) {
|
2399
|
+
if (!routeNames.hasOwnProperty(routeName)) {
|
2400
|
+
continue;
|
2401
|
+
}
|
2402
|
+
var route = routeNames[routeName];
|
2403
|
+
var handlers = Ember.A(route.handlers);
|
2404
|
+
buildSubTree.call(this, routeTree, route);
|
2405
|
+
}
|
2406
|
+
|
2407
|
+
return arrayizeChildren({ children: routeTree }).children[0];
|
2408
|
+
}).property('router'),
|
2409
|
+
|
2410
|
+
sendTree: function() {
|
2411
|
+
var routeTree = this.get('routeTree');
|
2412
|
+
this.sendMessage('routeTree', { tree: routeTree });
|
2413
|
+
}
|
2414
|
+
});
|
2415
|
+
|
2416
|
+
var buildSubTree = function(routeTree, route) {
|
2417
|
+
var handlers = route.handlers;
|
2418
|
+
var subTree = routeTree, item,
|
2419
|
+
routeClassName, routeHandler, controllerName,
|
2420
|
+
controllerClassName, container, templateName,
|
2421
|
+
controllerFactory;
|
2422
|
+
for (var i = 0; i < handlers.length; i++) {
|
2423
|
+
item = handlers[i];
|
2424
|
+
var handler = item.handler;
|
2425
|
+
if (subTree[handler] === undefined) {
|
2426
|
+
routeClassName = classify(handler.replace(/\./g, '_')) + 'Route';
|
2427
|
+
container = this.get('application.__container__');
|
2428
|
+
routeHandler = container.lookup('router:main').router.getHandler(handler);
|
2429
|
+
controllerName = routeHandler.get('controllerName') || routeHandler.get('routeName');
|
2430
|
+
controllerClassName = classify(controllerName.replace(/\./g, '_')) + 'Controller';
|
2431
|
+
controllerFactory = container.lookupFactory('controller:' + controllerName);
|
2432
|
+
templateName = handler.replace(/\./g, '/');
|
2433
|
+
|
2434
|
+
subTree[handler] = {
|
2435
|
+
value: {
|
2436
|
+
name: handler,
|
2437
|
+
routeHandler: {
|
2438
|
+
className: routeClassName,
|
2439
|
+
name: handler
|
2440
|
+
},
|
2441
|
+
controller: {
|
2442
|
+
className: controllerClassName,
|
2443
|
+
name: controllerName,
|
2444
|
+
exists: controllerFactory ? true : false
|
2445
|
+
},
|
2446
|
+
template: {
|
2447
|
+
name: templateName
|
2448
|
+
}
|
2449
|
+
}
|
2450
|
+
};
|
2451
|
+
|
2452
|
+
if (i === handlers.length - 1) {
|
2453
|
+
// it is a route, get url
|
2454
|
+
subTree[handler].value.url = getURL(container, route.segments);
|
2455
|
+
subTree[handler].value.type = 'route';
|
2456
|
+
} else {
|
2457
|
+
// it is a resource, set children object
|
2458
|
+
subTree[handler].children = {};
|
2459
|
+
subTree[handler].value.type = 'resource';
|
2460
|
+
}
|
2461
|
+
|
2462
|
+
}
|
2463
|
+
subTree = subTree[handler].children;
|
2464
|
+
}
|
2465
|
+
};
|
2466
|
+
|
2467
|
+
function arrayizeChildren(routeTree) {
|
2468
|
+
var obj = { value: routeTree.value };
|
2469
|
+
|
2470
|
+
if (routeTree.children) {
|
2471
|
+
var childrenArray = [];
|
2472
|
+
for(var i in routeTree.children) {
|
2473
|
+
var route = routeTree.children[i];
|
2474
|
+
childrenArray.push(arrayizeChildren(route));
|
2475
|
+
}
|
2476
|
+
obj.children = childrenArray;
|
2477
|
+
}
|
2478
|
+
|
2479
|
+
return obj;
|
2480
|
+
}
|
2481
|
+
|
2482
|
+
function getURL(container, segments) {
|
2483
|
+
var locationImplementation = container.lookup('router:main').location;
|
2484
|
+
var url = [];
|
2485
|
+
for (var i = 0; i < segments.length; i++) {
|
2486
|
+
var name = null;
|
2487
|
+
|
2488
|
+
try {
|
2489
|
+
name = segments[i].generate();
|
2490
|
+
} catch (e) {
|
2491
|
+
// is dynamic
|
2492
|
+
name = ':' + segments[i].name;
|
2493
|
+
}
|
2494
|
+
if (name) {
|
2495
|
+
url.push(name);
|
2496
|
+
}
|
2497
|
+
}
|
2498
|
+
|
2499
|
+
url = url.join('/');
|
2500
|
+
|
2501
|
+
if (url.match(/_unused_dummy_/)) {
|
2502
|
+
url = '';
|
2503
|
+
} else {
|
2504
|
+
url = '/' + url;
|
2505
|
+
url = locationImplementation.formatURL(url);
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
return url;
|
2509
|
+
}
|
2510
|
+
|
2511
|
+
__exports__["default"] = RouteDebug;
|
2512
|
+
});
|
2513
|
+
define("view_debug",
|
2514
|
+
["mixins/port_mixin","exports"],
|
2515
|
+
function(__dependency1__, __exports__) {
|
2516
|
+
"use strict";
|
2517
|
+
var PortMixin = __dependency1__["default"];
|
2518
|
+
|
2519
|
+
var layerDiv,
|
2520
|
+
previewDiv,
|
2521
|
+
highlightedElement,
|
2522
|
+
previewedElement,
|
2523
|
+
$ = Ember.$,
|
2524
|
+
later = Ember.run.later,
|
2525
|
+
computed = Ember.computed,
|
2526
|
+
oneWay = computed.oneWay;
|
2527
|
+
|
2528
|
+
var ViewDebug = Ember.Object.extend(PortMixin, {
|
2529
|
+
|
2530
|
+
namespace: null,
|
2531
|
+
|
2532
|
+
application: oneWay('namespace.application').readOnly(),
|
2533
|
+
adapter: oneWay('namespace.adapter').readOnly(),
|
2534
|
+
port: oneWay('namespace.port').readOnly(),
|
2535
|
+
objectInspector: oneWay('namespace.objectInspector').readOnly(),
|
2536
|
+
|
2537
|
+
retainedObjects: [],
|
2538
|
+
|
2539
|
+
_durations: {},
|
2540
|
+
|
2541
|
+
options: {},
|
2542
|
+
|
2543
|
+
portNamespace: 'view',
|
2544
|
+
|
2545
|
+
messages: {
|
2546
|
+
getTree: function() {
|
2547
|
+
this.sendTree();
|
2548
|
+
},
|
2549
|
+
hideLayer: function() {
|
2550
|
+
this.hideLayer();
|
2551
|
+
},
|
2552
|
+
showLayer: function(message) {
|
2553
|
+
this.showLayer(message.objectId);
|
2554
|
+
},
|
2555
|
+
previewLayer: function(message) {
|
2556
|
+
this.previewLayer(message.objectId);
|
2557
|
+
},
|
2558
|
+
hidePreview: function(message) {
|
2559
|
+
this.hidePreview(message.objectId);
|
2560
|
+
},
|
2561
|
+
inspectViews: function(message) {
|
2562
|
+
if (message.inspect) {
|
2563
|
+
this.startInspecting();
|
2564
|
+
} else {
|
2565
|
+
this.stopInspecting();
|
2566
|
+
}
|
2567
|
+
},
|
2568
|
+
inspectElement: function(message) {
|
2569
|
+
this.inspectElement(message.objectId);
|
2570
|
+
},
|
2571
|
+
setOptions: function(message) {
|
2572
|
+
this.set('options', message.options);
|
2573
|
+
this.sendTree();
|
2574
|
+
},
|
2575
|
+
sendModelToConsole: function(message) {
|
2576
|
+
var view = this.get('objectInspector').sentObjects[message.viewId];
|
2577
|
+
var model = this.modelForView(view);
|
2578
|
+
if (model) {
|
2579
|
+
this.get('objectInspector').sendValueToConsole(model);
|
2580
|
+
}
|
2581
|
+
}
|
2582
|
+
},
|
2583
|
+
|
2584
|
+
init: function() {
|
2585
|
+
this._super();
|
2586
|
+
var self = this;
|
2587
|
+
|
2588
|
+
this.viewListener();
|
2589
|
+
this.retainedObjects = [];
|
2590
|
+
this.options = {};
|
2591
|
+
|
2592
|
+
layerDiv = $('<div>').appendTo('body').get(0);
|
2593
|
+
layerDiv.style.display = 'none';
|
2594
|
+
layerDiv.setAttribute('data-label', 'layer-div');
|
2595
|
+
|
2596
|
+
previewDiv = $('<div>').appendTo('body').css('pointer-events', 'none').get(0);
|
2597
|
+
previewDiv.style.display = 'none';
|
2598
|
+
previewDiv.setAttribute('data-label', 'preview-div');
|
2599
|
+
|
2600
|
+
$(window).on('resize.' + this.get('eventNamespace'), function() {
|
2601
|
+
if (highlightedElement) {
|
2602
|
+
self.highlightView(highlightedElement);
|
2603
|
+
}
|
2604
|
+
});
|
2605
|
+
},
|
2606
|
+
|
2607
|
+
|
2608
|
+
updateDurations: function(durations) {
|
2609
|
+
for (var guid in durations) {
|
2610
|
+
if (!durations.hasOwnProperty(guid)) {
|
2611
|
+
continue;
|
2612
|
+
}
|
2613
|
+
this._durations[guid] = durations[guid];
|
2614
|
+
}
|
2615
|
+
this.sendTree();
|
2616
|
+
},
|
2617
|
+
|
2618
|
+
retainObject: function(object) {
|
2619
|
+
this.retainedObjects.push(object);
|
2620
|
+
return this.get('objectInspector').retainObject(object);
|
2621
|
+
},
|
2622
|
+
|
2623
|
+
releaseCurrentObjects: function() {
|
2624
|
+
var self = this;
|
2625
|
+
this.retainedObjects.forEach(function(item) {
|
2626
|
+
self.get('objectInspector').releaseObject(Ember.guidFor(item));
|
2627
|
+
});
|
2628
|
+
this.retainedObjects = [];
|
2629
|
+
},
|
2630
|
+
|
2631
|
+
eventNamespace: Ember.computed(function() {
|
2632
|
+
return 'view_debug_' + Ember.guidFor(this);
|
2633
|
+
}).property(),
|
2634
|
+
|
2635
|
+
willDestroy: function() {
|
2636
|
+
this._super();
|
2637
|
+
$(window).off(this.get('eventNamespace'));
|
2638
|
+
$(layerDiv).remove();
|
2639
|
+
$(previewDiv).remove();
|
2640
|
+
Ember.View.removeMutationListener(this.viewTreeChanged);
|
2641
|
+
this.releaseCurrentObjects();
|
2642
|
+
this.stopInspecting();
|
2643
|
+
},
|
2644
|
+
|
2645
|
+
inspectElement: function(objectId) {
|
2646
|
+
var view = this.get('objectInspector').sentObjects[objectId];
|
2647
|
+
if (view && view.get('element')) {
|
2648
|
+
this.get('adapter').inspectElement(view.get('element'));
|
2649
|
+
}
|
2650
|
+
},
|
2651
|
+
|
2652
|
+
sendTree: function() {
|
2653
|
+
Ember.run.scheduleOnce('afterRender', this, this.scheduledSendTree);
|
2654
|
+
},
|
2655
|
+
|
2656
|
+
startInspecting: function() {
|
2657
|
+
var self = this, viewElem = null;
|
2658
|
+
this.sendMessage('startInspecting', {});
|
2659
|
+
|
2660
|
+
// we don't want the preview div to intercept the mousemove event
|
2661
|
+
$(previewDiv).css('pointer-events', 'none');
|
2662
|
+
|
2663
|
+
$('body').on('mousemove.inspect-' + this.get('eventNamespace'), function(e) {
|
2664
|
+
var originalTarget = $(e.target), oldViewElem = viewElem;
|
2665
|
+
viewElem = self.findNearestView(originalTarget);
|
2666
|
+
if (viewElem) {
|
2667
|
+
self.highlightView(viewElem, true);
|
2668
|
+
}
|
2669
|
+
})
|
2670
|
+
.on('mousedown.inspect-' + this.get('eventNamespace'), function() {
|
2671
|
+
// prevent app-defined clicks from being fired
|
2672
|
+
$(previewDiv).css('pointer-events', '')
|
2673
|
+
.one('mouseup', function() {
|
2674
|
+
// chrome
|
2675
|
+
return pinView();
|
2676
|
+
});
|
2677
|
+
})
|
2678
|
+
.on('mouseup.inspect-' + this.get('eventNamespace'), function() {
|
2679
|
+
// firefox
|
2680
|
+
return pinView();
|
2681
|
+
})
|
2682
|
+
.css('cursor', '-webkit-zoom-in');
|
2683
|
+
|
2684
|
+
function pinView() {
|
2685
|
+
if (viewElem) {
|
2686
|
+
self.highlightView(viewElem);
|
2687
|
+
var view = self.get('objectInspector').sentObjects[viewElem.id];
|
2688
|
+
if (view instanceof Ember.Component) {
|
2689
|
+
self.get('objectInspector').sendObject(view);
|
2690
|
+
}
|
2691
|
+
}
|
2692
|
+
self.stopInspecting();
|
2693
|
+
return false;
|
2694
|
+
}
|
2695
|
+
},
|
2696
|
+
|
2697
|
+
findNearestView: function(elem) {
|
2698
|
+
var viewElem, view;
|
2699
|
+
if (!elem || elem.length === 0) { return null; }
|
2700
|
+
if (elem.hasClass('ember-view')) {
|
2701
|
+
viewElem = elem.get(0);
|
2702
|
+
view = this.get('objectInspector').sentObjects[viewElem.id];
|
2703
|
+
if (view && this.shouldShowView(view)) {
|
2704
|
+
return viewElem;
|
2705
|
+
}
|
2706
|
+
}
|
2707
|
+
return this.findNearestView($(elem).parents('.ember-view:first'));
|
2708
|
+
},
|
2709
|
+
|
2710
|
+
stopInspecting: function() {
|
2711
|
+
$('body')
|
2712
|
+
.off('mousemove.inspect-' + this.get('eventNamespace'))
|
2713
|
+
.off('mousedown.inspect-' + this.get('eventNamespace'))
|
2714
|
+
.off('mouseup.inspect-' + this.get('eventNamespace'))
|
2715
|
+
.off('click.inspect-' + this.get('eventNamespace'))
|
2716
|
+
.css('cursor', '');
|
2717
|
+
|
2718
|
+
this.hidePreview();
|
2719
|
+
this.sendMessage('stopInspecting', {});
|
2720
|
+
},
|
2721
|
+
|
2722
|
+
scheduledSendTree: function() {
|
2723
|
+
var self = this;
|
2724
|
+
// Send out of band
|
2725
|
+
later(function() {
|
2726
|
+
if (self.isDestroying) {
|
2727
|
+
return;
|
2728
|
+
}
|
2729
|
+
self.releaseCurrentObjects();
|
2730
|
+
var tree = self.viewTree();
|
2731
|
+
if (tree) {
|
2732
|
+
self.sendMessage('viewTree', {
|
2733
|
+
tree: tree
|
2734
|
+
});
|
2735
|
+
}
|
2736
|
+
}, 50);
|
2737
|
+
},
|
2738
|
+
|
2739
|
+
viewListener: function() {
|
2740
|
+
var self = this;
|
2741
|
+
|
2742
|
+
this.viewTreeChanged = function() {
|
2743
|
+
self.sendTree();
|
2744
|
+
self.hideLayer();
|
2745
|
+
};
|
2746
|
+
|
2747
|
+
Ember.View.addMutationListener(this.viewTreeChanged);
|
2748
|
+
},
|
2749
|
+
|
2750
|
+
viewTree: function() {
|
2751
|
+
var emberApp = this.get('application');
|
2752
|
+
if (!emberApp) {
|
2753
|
+
return false;
|
2754
|
+
}
|
2755
|
+
|
2756
|
+
var applicationViewId = $(emberApp.rootElement).find('> .ember-view').attr('id');
|
2757
|
+
var rootView = Ember.View.views[applicationViewId];
|
2758
|
+
// In case of App.reset view is destroyed
|
2759
|
+
if (!rootView) {
|
2760
|
+
return false;
|
2761
|
+
}
|
2762
|
+
var retained = [];
|
2763
|
+
|
2764
|
+
var children = [];
|
2765
|
+
var treeId = this.retainObject(retained);
|
2766
|
+
|
2767
|
+
var tree = { value: this.inspectView(rootView, retained), children: children, treeId: treeId };
|
2768
|
+
|
2769
|
+
this.appendChildren(rootView, children, retained);
|
2770
|
+
|
2771
|
+
return tree;
|
2772
|
+
},
|
2773
|
+
|
2774
|
+
modelForView: function(view) {
|
2775
|
+
var controller = view.get('controller');
|
2776
|
+
var model = controller.get('model');
|
2777
|
+
if (view.get('context') !== controller) {
|
2778
|
+
model = view.get('context');
|
2779
|
+
}
|
2780
|
+
return model;
|
2781
|
+
},
|
2782
|
+
|
2783
|
+
inspectView: function(view, retained) {
|
2784
|
+
var templateName = view.get('templateName') || view.get('_debugTemplateName'),
|
2785
|
+
viewClass = shortViewName(view), name;
|
2786
|
+
|
2787
|
+
var tagName = view.get('tagName');
|
2788
|
+
if (tagName === '') {
|
2789
|
+
tagName = '(virtual)';
|
2790
|
+
}
|
2791
|
+
|
2792
|
+
tagName = tagName || 'div';
|
2793
|
+
|
2794
|
+
var controller = view.get('controller');
|
2795
|
+
|
2796
|
+
name = viewDescription(view);
|
2797
|
+
|
2798
|
+
|
2799
|
+
var viewId = this.retainObject(view);
|
2800
|
+
retained.push(viewId);
|
2801
|
+
|
2802
|
+
var timeToRender = this._durations[viewId];
|
2803
|
+
|
2804
|
+
var value = {
|
2805
|
+
viewClass: viewClass,
|
2806
|
+
completeViewClass: viewName(view),
|
2807
|
+
objectId: viewId,
|
2808
|
+
duration: timeToRender,
|
2809
|
+
name: name,
|
2810
|
+
template: templateName || '(inline)',
|
2811
|
+
tagName: tagName,
|
2812
|
+
isVirtual: view.get('isVirtual'),
|
2813
|
+
isComponent: (view instanceof Ember.Component)
|
2814
|
+
};
|
2815
|
+
|
2816
|
+
if (controller && !(view instanceof Ember.Component)) {
|
2817
|
+
value.controller = {
|
2818
|
+
name: shortControllerName(controller),
|
2819
|
+
completeName: controllerName(controller),
|
2820
|
+
objectId: this.retainObject(controller)
|
2821
|
+
};
|
2822
|
+
|
2823
|
+
var model = this.modelForView(view);
|
2824
|
+
if (model) {
|
2825
|
+
if(Ember.Object.detectInstance(model) || Ember.typeOf(model) === 'array') {
|
2826
|
+
value.model = {
|
2827
|
+
name: shortModelName(model),
|
2828
|
+
completeName: modelName(model),
|
2829
|
+
objectId: this.retainObject(model),
|
2830
|
+
type: 'type-ember-object'
|
2831
|
+
};
|
2832
|
+
} else {
|
2833
|
+
value.model = {
|
2834
|
+
name: this.get('objectInspector').inspect(model),
|
2835
|
+
type: 'type-' + Ember.typeOf(model)
|
2836
|
+
};
|
2837
|
+
}
|
2838
|
+
}
|
2839
|
+
}
|
2840
|
+
|
2841
|
+
return value;
|
2842
|
+
},
|
2843
|
+
|
2844
|
+
appendChildren: function(view, children, retained) {
|
2845
|
+
var self = this;
|
2846
|
+
var childViews = view.get('_childViews'),
|
2847
|
+
controller = view.get('controller');
|
2848
|
+
|
2849
|
+
childViews.forEach(function(childView) {
|
2850
|
+
if (!(childView instanceof Ember.Object)) { return; }
|
2851
|
+
|
2852
|
+
if (self.shouldShowView(childView)) {
|
2853
|
+
var grandChildren = [];
|
2854
|
+
children.push({ value: self.inspectView(childView, retained), children: grandChildren });
|
2855
|
+
self.appendChildren(childView, grandChildren, retained);
|
2856
|
+
} else {
|
2857
|
+
self.appendChildren(childView, children, retained);
|
2858
|
+
}
|
2859
|
+
});
|
2860
|
+
},
|
2861
|
+
|
2862
|
+
shouldShowView: function(view) {
|
2863
|
+
return (this.options.allViews || this.hasOwnController(view) || this.hasOwnContext(view)) &&
|
2864
|
+
(this.options.components || !(view instanceof Ember.Component)) &&
|
2865
|
+
(!view.get('isVirtual') || this.hasOwnController(view) || this.hasOwnContext(view));
|
2866
|
+
},
|
2867
|
+
|
2868
|
+
hasOwnController: function(view) {
|
2869
|
+
return view.get('controller') !== view.get('_parentView.controller') &&
|
2870
|
+
((view instanceof Ember.Component) || !(view.get('_parentView.controller') instanceof Ember.Component));
|
2871
|
+
},
|
2872
|
+
|
2873
|
+
hasOwnContext: function(view) {
|
2874
|
+
return view.get('context') !== view.get('_parentView.context') && !(view.get('_parentView') instanceof Ember.Component);
|
2875
|
+
},
|
2876
|
+
|
2877
|
+
highlightView: function(element, preview) {
|
2878
|
+
var self = this;
|
2879
|
+
var range, view, rect, div;
|
2880
|
+
|
2881
|
+
if (!element) { return; }
|
2882
|
+
|
2883
|
+
if (preview) {
|
2884
|
+
previewedElement = element;
|
2885
|
+
div = previewDiv;
|
2886
|
+
} else {
|
2887
|
+
this.hideLayer();
|
2888
|
+
highlightedElement = element;
|
2889
|
+
div = layerDiv;
|
2890
|
+
this.hidePreview();
|
2891
|
+
}
|
2892
|
+
|
2893
|
+
if (element instanceof Ember.View && element.get('isVirtual')) {
|
2894
|
+
view = element;
|
2895
|
+
if (view.get('isVirtual')) {
|
2896
|
+
range = virtualRange(view);
|
2897
|
+
rect = range.getBoundingClientRect();
|
2898
|
+
}
|
2899
|
+
} else if (element instanceof Ember.View) {
|
2900
|
+
view = element;
|
2901
|
+
element = view.get('element');
|
2902
|
+
if (!element) { return; }
|
2903
|
+
rect = element.getBoundingClientRect();
|
2904
|
+
} else {
|
2905
|
+
view = Ember.View.views[element.id];
|
2906
|
+
rect = element.getBoundingClientRect();
|
2907
|
+
}
|
2908
|
+
|
2909
|
+
// take into account the scrolling position as mentioned in docs
|
2910
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/element.getBoundingClientRect
|
2911
|
+
rect = $().extend({}, rect);
|
2912
|
+
rect.top = rect.top + window.scrollY;
|
2913
|
+
rect.left = rect.left + window.scrollX;
|
2914
|
+
|
2915
|
+
var templateName = view.get('templateName') || view.get('_debugTemplateName'),
|
2916
|
+
controller = view.get('controller'),
|
2917
|
+
model = controller && controller.get('model');
|
2918
|
+
|
2919
|
+
$(div).css(rect);
|
2920
|
+
$(div).css({
|
2921
|
+
display: "block",
|
2922
|
+
position: "absolute",
|
2923
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
2924
|
+
border: "2px solid rgb(102, 102, 102)",
|
2925
|
+
padding: "0",
|
2926
|
+
right: "auto",
|
2927
|
+
direction: "ltr",
|
2928
|
+
boxSizing: "border-box",
|
2929
|
+
color: "rgb(51, 51, 255)",
|
2930
|
+
fontFamily: "Menlo, sans-serif",
|
2931
|
+
minHeight: 63,
|
2932
|
+
zIndex: 10000
|
2933
|
+
});
|
2934
|
+
|
2935
|
+
var output = "";
|
2936
|
+
|
2937
|
+
if (!preview) {
|
2938
|
+
output = "<span class='close' data-label='layer-close'>×</span>";
|
2939
|
+
}
|
2940
|
+
|
2941
|
+
if (templateName) {
|
2942
|
+
output += "<p class='template'><span>template</span>=<span data-label='layer-template'>" + escapeHTML(templateName) + "</span></p>";
|
2943
|
+
}
|
2944
|
+
|
2945
|
+
if (!(view instanceof Ember.Component)) {
|
2946
|
+
if (controller) {
|
2947
|
+
output += "<p class='controller'><span>controller</span>=<span data-label='layer-controller'>" + escapeHTML(controllerName(controller)) + "</span></p>";
|
2948
|
+
}
|
2949
|
+
output += "<p class='view'><span>view</span>=<span data-label='layer-view'>" + escapeHTML(viewName(view)) + "</span></p>";
|
2950
|
+
} else {
|
2951
|
+
output += "<p class='component'><span>component</span>=<span data-label='layer-component'>" + escapeHTML(viewName(view)) + "</span></p>";
|
2952
|
+
}
|
2953
|
+
|
2954
|
+
if (model) {
|
2955
|
+
var modelName = this.get('objectInspector').inspect(model);
|
2956
|
+
output += "<p class='model'><span>model</span>=<span data-label='layer-model'>" + escapeHTML(modelName) + "</span></p>";
|
2957
|
+
}
|
2958
|
+
|
2959
|
+
$(div).html(output);
|
2960
|
+
|
2961
|
+
$('p', div).css({ float: 'left', margin: 0, backgroundColor: 'rgba(255, 255, 255, 0.9)', padding: '5px', color: 'rgb(0, 0, 153)' });
|
2962
|
+
$('p.model', div).css({ clear: 'left' });
|
2963
|
+
$('p span:first-child', div).css({ color: 'rgb(153, 153, 0)' });
|
2964
|
+
$('p span:last-child', div).css({ color: 'rgb(153, 0, 153)' });
|
2965
|
+
|
2966
|
+
if (!preview) {
|
2967
|
+
$('span.close', div).css({
|
2968
|
+
float: 'right',
|
2969
|
+
margin: '5px',
|
2970
|
+
background: '#666',
|
2971
|
+
color: '#eee',
|
2972
|
+
fontFamily: 'helvetica, sans-serif',
|
2973
|
+
fontSize: '12px',
|
2974
|
+
width: 16,
|
2975
|
+
height: 16,
|
2976
|
+
lineHeight: '14px',
|
2977
|
+
borderRadius: 16,
|
2978
|
+
textAlign: 'center',
|
2979
|
+
cursor: 'pointer'
|
2980
|
+
}).on('click', function() {
|
2981
|
+
self.hideLayer();
|
2982
|
+
return false;
|
2983
|
+
}).on('mouseup mousedown', function() {
|
2984
|
+
// prevent re-pinning
|
2985
|
+
return false;
|
2986
|
+
});
|
2987
|
+
}
|
2988
|
+
|
2989
|
+
$('p.view span:last-child', div).css({ cursor: 'pointer' }).click(function() {
|
2990
|
+
self.get('objectInspector').sendObject(view);
|
2991
|
+
});
|
2992
|
+
|
2993
|
+
$('p.controller span:last-child', div).css({ cursor: 'pointer' }).click(function() {
|
2994
|
+
self.get('objectInspector').sendObject(controller);
|
2995
|
+
});
|
2996
|
+
|
2997
|
+
$('p.component span:last-child', div).css({ cursor: 'pointer' }).click(function() {
|
2998
|
+
self.get('objectInspector').sendObject(view);
|
2999
|
+
});
|
3000
|
+
|
3001
|
+
$('p.template span:last-child', div).css({ cursor: 'pointer' }).click(function() {
|
3002
|
+
self.inspectElement(Ember.guidFor(view));
|
3003
|
+
});
|
3004
|
+
|
3005
|
+
if (model && ((model instanceof Ember.Object) || Ember.typeOf(model) === 'array')) {
|
3006
|
+
$('p.model span:last-child', div).css({ cursor: 'pointer' }).click(function() {
|
3007
|
+
self.get('objectInspector').sendObject(controller.get('model'));
|
3008
|
+
});
|
3009
|
+
}
|
3010
|
+
|
3011
|
+
if (!preview) {
|
3012
|
+
this.sendMessage('pinView', { objectId: Ember.guidFor(view) });
|
3013
|
+
}
|
3014
|
+
},
|
3015
|
+
|
3016
|
+
showLayer: function(objectId) {
|
3017
|
+
this.highlightView(this.get('objectInspector').sentObjects[objectId]);
|
3018
|
+
},
|
3019
|
+
|
3020
|
+
previewLayer: function(objectId) {
|
3021
|
+
this.highlightView(this.get('objectInspector').sentObjects[objectId], true);
|
3022
|
+
},
|
3023
|
+
|
3024
|
+
hideLayer: function() {
|
3025
|
+
this.sendMessage('unpinView', {});
|
3026
|
+
layerDiv.style.display = 'none';
|
3027
|
+
highlightedElement = null;
|
3028
|
+
},
|
3029
|
+
|
3030
|
+
hidePreview: function() {
|
3031
|
+
previewDiv.style.display = 'none';
|
3032
|
+
previewedElement = null;
|
3033
|
+
}
|
3034
|
+
});
|
3035
|
+
|
3036
|
+
function viewName(view) {
|
3037
|
+
var name = view.constructor.toString(), match;
|
3038
|
+
if (name.match(/\._/)) {
|
3039
|
+
name = "virtual";
|
3040
|
+
} else if (match = name.match(/\(subclass of (.*)\)/)) {
|
3041
|
+
name = match[1];
|
3042
|
+
}
|
3043
|
+
return name;
|
3044
|
+
}
|
3045
|
+
|
3046
|
+
function shortViewName(view) {
|
3047
|
+
var name = viewName(view);
|
3048
|
+
// jj-abrams-resolver adds `app@view:` and `app@component:`
|
3049
|
+
return name.replace(/.+(view|component):/, '').replace(/:$/, '');
|
3050
|
+
}
|
3051
|
+
|
3052
|
+
function modelName(model) {
|
3053
|
+
var name = '<Unknown model>';
|
3054
|
+
if (model.toString) {
|
3055
|
+
name = model.toString();
|
3056
|
+
}
|
3057
|
+
|
3058
|
+
|
3059
|
+
if (name.length > 50) {
|
3060
|
+
name = name.substr(0, 50) + '...';
|
3061
|
+
}
|
3062
|
+
return name;
|
3063
|
+
}
|
3064
|
+
|
3065
|
+
function shortModelName(model) {
|
3066
|
+
var name = modelName(model);
|
3067
|
+
// jj-abrams-resolver adds `app@model:`
|
3068
|
+
return name.replace(/<[^>]+@model:/g, '<');
|
3069
|
+
}
|
3070
|
+
|
3071
|
+
function controllerName(controller) {
|
3072
|
+
var key = controller.get('_debugContainerKey'),
|
3073
|
+
className = controller.constructor.toString(),
|
3074
|
+
name, match;
|
3075
|
+
|
3076
|
+
if (match = className.match(/^\(subclass of (.*)\)/)) {
|
3077
|
+
className = match[1];
|
3078
|
+
}
|
3079
|
+
|
3080
|
+
return className;
|
3081
|
+
}
|
3082
|
+
|
3083
|
+
function shortControllerName(controller) {
|
3084
|
+
var name = controllerName(controller);
|
3085
|
+
// jj-abrams-resolver adds `app@controller:` at the begining and `:` at the end
|
3086
|
+
return name.replace(/^.+@controller:/, '').replace(/:$/, '');
|
3087
|
+
}
|
3088
|
+
|
3089
|
+
function escapeHTML(string) {
|
3090
|
+
var div = document.createElement('div');
|
3091
|
+
div.appendChild(document.createTextNode(string));
|
3092
|
+
return div.innerHTML;
|
3093
|
+
}
|
3094
|
+
|
3095
|
+
function virtualRange(view) {
|
3096
|
+
var start, end;
|
3097
|
+
var morph = view.get('morph');
|
3098
|
+
|
3099
|
+
if (morph) {
|
3100
|
+
start = $('#' + morph.start)[0];
|
3101
|
+
end = $('#' + morph.end)[0];
|
3102
|
+
} else {
|
3103
|
+
// Support for metal-views
|
3104
|
+
morph = view.get('_morph');
|
3105
|
+
start = morph.start;
|
3106
|
+
end = morph.end;
|
3107
|
+
}
|
3108
|
+
|
3109
|
+
var range = document.createRange();
|
3110
|
+
range.setStartAfter(start);
|
3111
|
+
range.setEndBefore(end);
|
3112
|
+
|
3113
|
+
return range;
|
3114
|
+
}
|
3115
|
+
|
3116
|
+
function viewDescription(view) {
|
3117
|
+
var templateName = view.get('templateName') || view.get('_debugTemplateName'),
|
3118
|
+
name, viewClass = shortViewName(view), controller = view.get('controller'),
|
3119
|
+
parentClassName;
|
3120
|
+
|
3121
|
+
if (templateName) {
|
3122
|
+
name = templateName;
|
3123
|
+
} else if (view instanceof Ember.LinkView) {
|
3124
|
+
name = 'link';
|
3125
|
+
} else if (view.get('_parentView.controller') === controller || view instanceof Ember.Component) {
|
3126
|
+
var viewClassName = view.get('_debugContainerKey');
|
3127
|
+
if (viewClassName) {
|
3128
|
+
viewClassName = viewClassName.match(/\:(.*)/);
|
3129
|
+
if (viewClassName) {
|
3130
|
+
viewClassName = viewClassName[1];
|
3131
|
+
}
|
3132
|
+
}
|
3133
|
+
if (!viewClassName && viewClass) {
|
3134
|
+
viewClassName = viewClass.match(/\.(.*)/);
|
3135
|
+
if (viewClassName) {
|
3136
|
+
viewClassName = viewClassName[1];
|
3137
|
+
} else {
|
3138
|
+
viewClassName = viewClass;
|
3139
|
+
}
|
3140
|
+
|
3141
|
+
var shortName = viewClassName.match(/(.*)(View|Component)$/);
|
3142
|
+
if (shortName) {
|
3143
|
+
viewClassName = shortName[1];
|
3144
|
+
}
|
3145
|
+
}
|
3146
|
+
if (viewClassName) {
|
3147
|
+
name = Ember.String.camelize(viewClassName);
|
3148
|
+
}
|
3149
|
+
} else if (view.get('_parentView.controller') !== controller) {
|
3150
|
+
var key = controller.get('_debugContainerKey'),
|
3151
|
+
className = controller.constructor.toString();
|
3152
|
+
|
3153
|
+
if (key) {
|
3154
|
+
name = key.split(':')[1];
|
3155
|
+
} else {
|
3156
|
+
if (parentClassName = className.match(/^\(subclass of (.*)\)/)) {
|
3157
|
+
className = parentClassName[1];
|
3158
|
+
}
|
3159
|
+
name = className.split('.').pop();
|
3160
|
+
name = Ember.String.camelize(name);
|
3161
|
+
}
|
3162
|
+
}
|
3163
|
+
|
3164
|
+
if (!name) {
|
3165
|
+
name = '(inline view)';
|
3166
|
+
}
|
3167
|
+
return name;
|
3168
|
+
}
|
3169
|
+
|
3170
|
+
__exports__["default"] = ViewDebug;
|
3171
|
+
});
|
3172
|
+
|
3173
|
+
}("chrome"))
|