ember-inspector 4.11.0-alpha.2024.3.9 → 4.11.0-alpha.2024.4.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. package/.github/dependabot.yml +1 -0
  2. package/.github/workflows/build.yml +5 -26
  3. package/.github/workflows/plan-release.yml +83 -0
  4. package/.github/workflows/publish.yml +58 -0
  5. package/app/components/component-tree-arg.js +9 -0
  6. package/app/components/component-tree-item.hbs +18 -2
  7. package/app/components/object-inspector/dependent-keys.hbs +9 -5
  8. package/app/components/object-inspector/properties-all.hbs +1 -0
  9. package/app/components/object-inspector/properties-base.js +10 -0
  10. package/app/components/object-inspector/properties-grouped.hbs +1 -0
  11. package/app/components/object-inspector/property.hbs +12 -1
  12. package/app/components/object-inspector/property.ts +4 -2
  13. package/app/components/object-inspector.hbs +16 -2
  14. package/app/components/object-inspector.js +14 -0
  15. package/app/controllers/component-tree.js +54 -3
  16. package/app/routes/component-tree.js +0 -6
  17. package/app/services/adapters/web-extension.js +3 -3
  18. package/app/services/port.js +4 -0
  19. package/app/styles/component_tree.scss +13 -0
  20. package/app/utils/parse-text.ts +1 -0
  21. package/dist/bookmarklet/panes-3-16-0/assets/{chunk.143.ac621af5331b75527946.js → chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  22. package/dist/{firefox/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → bookmarklet/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  23. package/dist/bookmarklet/panes-3-16-0/assets/ember-inspector.css +13 -0
  24. package/dist/bookmarklet/panes-3-16-0/assets/ember-inspector.js +28 -24
  25. package/dist/bookmarklet/panes-3-16-0/assets/svg/code-source.svg +9 -0
  26. package/dist/bookmarklet/panes-3-16-0/assets/vendor.css +33 -0
  27. package/dist/bookmarklet/panes-3-16-0/assets/vendor.js +12 -10
  28. package/dist/bookmarklet/panes-3-16-0/ember_debug.js +453 -559
  29. package/dist/bookmarklet/panes-3-16-0/index.html +2 -2
  30. package/dist/chrome/manifest.json +2 -2
  31. package/dist/{firefox/panes-3-16-0/assets/chunk.143.ac621af5331b75527946.js → chrome/panes-3-16-0/assets/chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  32. package/dist/{bookmarklet/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → chrome/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  33. package/dist/chrome/panes-3-16-0/assets/ember-inspector.css +13 -0
  34. package/dist/chrome/panes-3-16-0/assets/ember-inspector.js +28 -24
  35. package/dist/chrome/panes-3-16-0/assets/svg/code-source.svg +9 -0
  36. package/dist/chrome/panes-3-16-0/assets/vendor.css +33 -0
  37. package/dist/chrome/panes-3-16-0/assets/vendor.js +12 -10
  38. package/dist/chrome/panes-3-16-0/ember_debug.js +453 -559
  39. package/dist/chrome/panes-3-16-0/index.html +2 -2
  40. package/dist/firefox/manifest.json +2 -2
  41. package/dist/{chrome/panes-3-16-0/assets/chunk.143.ac621af5331b75527946.js → firefox/panes-3-16-0/assets/chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  42. package/dist/{websocket/assets/chunk.178.e6b2f8bb19b9f072aa49.js → firefox/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  43. package/dist/firefox/panes-3-16-0/assets/ember-inspector.css +13 -0
  44. package/dist/firefox/panes-3-16-0/assets/ember-inspector.js +28 -24
  45. package/dist/firefox/panes-3-16-0/assets/svg/code-source.svg +9 -0
  46. package/dist/firefox/panes-3-16-0/assets/vendor.css +33 -0
  47. package/dist/firefox/panes-3-16-0/assets/vendor.js +12 -10
  48. package/dist/firefox/panes-3-16-0/ember_debug.js +453 -559
  49. package/dist/firefox/panes-3-16-0/index.html +2 -2
  50. package/dist/websocket/assets/{chunk.143.ac621af5331b75527946.js → chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  51. package/dist/{chrome/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → websocket/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  52. package/dist/websocket/assets/ember-inspector.css +13 -0
  53. package/dist/websocket/assets/ember-inspector.js +28 -24
  54. package/dist/websocket/assets/svg/code-source.svg +9 -0
  55. package/dist/websocket/assets/vendor.css +33 -0
  56. package/dist/websocket/assets/vendor.js +12 -10
  57. package/dist/websocket/ember_debug.js +453 -559
  58. package/dist/websocket/index.html +2 -2
  59. package/ember-cli-build.js +3 -4
  60. package/ember_debug/adapters/basic.js +4 -4
  61. package/ember_debug/adapters/web-extension.js +9 -5
  62. package/ember_debug/general-debug.js +3 -1
  63. package/ember_debug/libs/capture-render-tree.js +7 -426
  64. package/ember_debug/libs/render-tree.js +210 -31
  65. package/ember_debug/libs/view-inspection.js +28 -0
  66. package/ember_debug/object-inspector.js +92 -109
  67. package/ember_debug/route-debug.js +2 -3
  68. package/ember_debug/utils/ember.js +16 -0
  69. package/ember_debug/utils/get-object-name.js +4 -0
  70. package/ember_debug/utils/name-functions.js +1 -1
  71. package/ember_debug/utils/type-check.js +82 -12
  72. package/ember_debug/utils/version.js +37 -0
  73. package/ember_debug/view-debug.js +1 -1
  74. package/lib/ui/addon/styles/_goto-source.scss +30 -0
  75. package/lib/ui/addon/styles/addon.scss +1 -0
  76. package/lib/ui/addon/styles/toolbar/_index.scss +4 -0
  77. package/package.json +2 -1
  78. package/public/assets/svg/code-source.svg +9 -0
  79. package/skeletons/web-extension/manifest.json +2 -2
  80. package/tests/acceptance/object-inspector-test.js +68 -0
  81. package/tests/ember_debug/object-inspector-test.js +18 -8
  82. package/tests/ember_debug/view-debug-test.js +211 -69
  83. package/tests/index.html +1 -0
@@ -3,21 +3,27 @@ import DebugPort from './debug-port';
3
3
  import bound from 'ember-debug/utils/bound-method';
4
4
  import {
5
5
  isComputed,
6
- isDescriptor,
7
6
  getDescriptorFor,
8
7
  typeOf,
8
+ inspect,
9
9
  } from 'ember-debug/utils/type-check';
10
10
  import { compareVersion } from 'ember-debug/utils/version';
11
- import { inspect as emberInspect } from 'ember-debug/utils/ember/debug';
12
- import Ember, { EmberObject } from 'ember-debug/utils/ember';
11
+ import {
12
+ EmberObject,
13
+ meta as emberMeta,
14
+ VERSION,
15
+ CoreObject,
16
+ ObjectProxy,
17
+ ArrayProxy,
18
+ Service,
19
+ Component,
20
+ } from 'ember-debug/utils/ember';
13
21
  import { cacheFor, guidFor } from 'ember-debug/utils/ember/object/internals';
14
22
  import { _backburner, join } from 'ember-debug/utils/ember/runloop';
15
23
  import emberNames from './utils/ember-object-names';
16
24
  import getObjectName from './utils/get-object-name';
17
25
  import { EmberLoader } from 'ember-debug/utils/ember/loader';
18
26
 
19
- const { meta: emberMeta, VERSION, CoreObject, ObjectProxy } = Ember;
20
-
21
27
  const GlimmerComponent = (() => {
22
28
  try {
23
29
  return EmberLoader.require('@glimmer/component').default;
@@ -88,7 +94,7 @@ try {
88
94
 
89
95
  const HAS_GLIMMER_TRACKING = tagValue && tagValidate && track && tagForProperty;
90
96
 
91
- const keys = Object.keys || Ember.keys;
97
+ const keys = Object.keys;
92
98
 
93
99
  /**
94
100
  * Determine the type and get the value of the passed property
@@ -107,6 +113,12 @@ function inspectValue(object, key, computedValue) {
107
113
 
108
114
  // TODO: this is not very clean. We should refactor calculateCP, etc, rather than passing computedValue
109
115
  if (computedValue !== undefined) {
116
+ if (value instanceof HTMLElement) {
117
+ return {
118
+ type: 'type-object',
119
+ inspect: `<${value.tagName.toLowerCase()}>`,
120
+ };
121
+ }
110
122
  return { type: `type-${typeOf(value)}`, inspect: inspect(value) };
111
123
  }
112
124
 
@@ -115,89 +127,16 @@ function inspectValue(object, key, computedValue) {
115
127
  } else if (isComputed(object, key)) {
116
128
  string = '<computed>';
117
129
  return { type: 'type-descriptor', inspect: string };
118
- } else if (isDescriptor(value)) {
130
+ } else if (value?.isDescriptor) {
119
131
  return { type: 'type-descriptor', inspect: value.toString() };
132
+ } else if (value instanceof HTMLElement) {
133
+ return { type: 'type-object', inspect: value.tagName.toLowerCase() };
120
134
  } else {
121
135
  return { type: `type-${typeOf(value)}`, inspect: inspect(value) };
122
136
  }
123
137
  }
124
138
 
125
- function inspect(value) {
126
- if (typeof value === 'function') {
127
- return 'function() { ... }';
128
- } else if (value instanceof EmberObject) {
129
- return value.toString();
130
- } else if (typeOf(value) === 'array') {
131
- if (value.length === 0) {
132
- return '[]';
133
- } else if (value.length === 1) {
134
- return `[ ${inspect(value[0])} ]`;
135
- } else {
136
- return `[ ${inspect(value[0])}, ... ]`;
137
- }
138
- } else if (value instanceof Error) {
139
- return `Error: ${value.message}`;
140
- } else if (value === null) {
141
- return 'null';
142
- } else if (typeOf(value) === 'date') {
143
- return value.toString();
144
- } else if (typeof value === 'object') {
145
- // `Ember.inspect` is able to handle this use case,
146
- // but it is very slow as it loops over all props,
147
- // so summarize to just first 2 props
148
- // if it defines a toString, we use that instead
149
- if (
150
- typeof value.toString === 'function' &&
151
- value.toString !== Object.prototype.toString &&
152
- value.toString !== Function.prototype.toString
153
- ) {
154
- try {
155
- return `<Object:${value.toString()}>`;
156
- } catch (e) {
157
- //
158
- }
159
- }
160
- let ret = [];
161
- let v;
162
- let count = 0;
163
- let broken = false;
164
-
165
- for (let key in value) {
166
- if (!('hasOwnProperty' in value) || value.hasOwnProperty(key)) {
167
- if (count++ > 1) {
168
- broken = true;
169
- break;
170
- }
171
- v = value[key];
172
- if (v === 'toString') {
173
- continue;
174
- } // ignore useless items
175
- if (typeOf(v).includes('function')) {
176
- v = 'function() { ... }';
177
- }
178
- if (typeOf(v) === 'array') {
179
- v = `[Array : ${v.length}]`;
180
- }
181
- if (typeOf(v) === 'object') {
182
- v = '[Object]';
183
- }
184
- ret.push(`${key}: ${v}`);
185
- }
186
- }
187
- let suffix = ' }';
188
- if (broken) {
189
- suffix = ' ...}';
190
- }
191
- return `{ ${ret.join(', ')}${suffix}`;
192
- } else {
193
- return emberInspect(value);
194
- }
195
- }
196
-
197
139
  function isMandatorySetter(descriptor) {
198
- if (descriptor.set && descriptor.set === Ember.MANDATORY_SETTER_FUNCTION) {
199
- return true;
200
- }
201
140
  if (
202
141
  descriptor.set &&
203
142
  Function.prototype.toString
@@ -209,7 +148,7 @@ function isMandatorySetter(descriptor) {
209
148
  return false;
210
149
  }
211
150
 
212
- function getTagTrackedProps(tag, ownTag, level = 0) {
151
+ function getTagTrackedTags(tag, ownTag, level = 0) {
213
152
  const props = [];
214
153
  // do not include tracked properties from dependencies
215
154
  if (!tag || level > 1) {
@@ -219,13 +158,13 @@ function getTagTrackedProps(tag, ownTag, level = 0) {
219
158
  if (tag.subtag && !Array.isArray(tag.subtag)) {
220
159
  if (tag.subtag._propertyKey) props.push(tag.subtag);
221
160
 
222
- props.push(...getTagTrackedProps(tag.subtag, ownTag, level + 1));
161
+ props.push(...getTagTrackedTags(tag.subtag, ownTag, level + 1));
223
162
  }
224
163
  if (subtags) {
225
164
  subtags.forEach((t) => {
226
165
  if (t === ownTag) return;
227
166
  if (t._propertyKey) props.push(t);
228
- props.push(...getTagTrackedProps(t, ownTag, level + 1));
167
+ props.push(...getTagTrackedTags(t, ownTag, level + 1));
229
168
  });
230
169
  }
231
170
  return props;
@@ -238,46 +177,67 @@ function getTrackedDependencies(object, property, tagInfo) {
238
177
  const cpDesc = emberMeta(object).peekDescriptors(property);
239
178
  const dependentKeys = [];
240
179
  if (cpDesc) {
241
- dependentKeys.push(...(cpDesc._dependentKeys || []));
180
+ dependentKeys.push(
181
+ ...(cpDesc._dependentKeys || []).map((k) => ({ name: k }))
182
+ );
242
183
  }
243
184
  if (HAS_GLIMMER_TRACKING) {
244
185
  const ownTag = tagForProperty(object, property);
245
- const props = getTagTrackedProps(tag, ownTag);
186
+ const tags = getTagTrackedTags(tag, ownTag);
246
187
  const mapping = {};
247
- let maxRevision = tagInfo.revision ?? 0;
248
- let minRevision = Infinity;
249
- props.forEach((t) => {
188
+ let maxRevision = tagValue(tag);
189
+ tags.forEach((t) => {
250
190
  const p =
251
191
  (t._object ? getObjectName(t._object) + '.' : '') + t._propertyKey;
252
- const [objName, ...props] = p.split('.');
192
+ const [objName, prop] = p.split('.');
253
193
  mapping[objName] = mapping[objName] || new Set();
254
- maxRevision = Math.max(maxRevision, t.revision);
255
- minRevision = Math.min(minRevision, t.revision);
256
- props.forEach((p) => mapping[objName].add([p, t.revision]));
194
+ const value = tagValue(t);
195
+ if (prop) {
196
+ mapping[objName].add([prop, value]);
197
+ }
257
198
  });
258
199
 
259
- const hasChange = maxRevision !== minRevision;
200
+ const hasChange =
201
+ (tagInfo.revision && maxRevision !== tagInfo.revision) || false;
202
+
203
+ const names = new Set();
260
204
 
261
205
  Object.entries(mapping).forEach(([objName, props]) => {
206
+ if (names.has(objName)) {
207
+ return;
208
+ }
209
+ names.add(objName);
262
210
  if (props.size > 1) {
263
- dependentKeys.push(objName);
211
+ dependentKeys.push({ name: objName });
264
212
  props.forEach((p) => {
265
- const changed = hasChange && p[1] >= maxRevision ? ' 🔸' : '';
266
- dependentKeys.push(' • -- ' + p[0] + changed);
213
+ const changed = hasChange && p[1] > tagInfo.revision;
214
+ const obj = {
215
+ child: p[0],
216
+ };
217
+ if (changed) {
218
+ obj.changed = true;
219
+ }
220
+ dependentKeys.push(obj);
267
221
  });
268
222
  }
269
223
  if (props.size === 1) {
270
224
  const p = [...props][0];
271
- const changed = hasChange && p[1] >= maxRevision ? ' 🔸' : '';
272
- dependentKeys.push(objName + '.' + p[0] + changed);
225
+ const changed = hasChange && p[1] > tagInfo.revision;
226
+ const obj = {
227
+ name: objName + '.' + p[0],
228
+ };
229
+ if (changed) {
230
+ obj.changed = true;
231
+ }
232
+ dependentKeys.push(obj);
273
233
  }
274
234
  if (props.size === 0) {
275
- dependentKeys.push(objName);
235
+ dependentKeys.push({ name: objName });
276
236
  }
277
237
  });
278
238
  }
279
239
 
280
- return [...new Set([...dependentKeys])];
240
+ return [...dependentKeys];
281
241
  }
282
242
 
283
243
  export default class extends DebugPort {
@@ -431,6 +391,9 @@ export default class extends DebugPort {
431
391
  sendToConsole(message) {
432
392
  this.sendToConsole(message.objectId, message.property);
433
393
  },
394
+ gotoSource(message) {
395
+ this.gotoSource(message.objectId, message.property);
396
+ },
434
397
  sendControllerToConsole(message) {
435
398
  const container = this.namespace?.owner;
436
399
  this.sendValueToConsole(container.lookup(`controller:${message.name}`));
@@ -516,6 +479,26 @@ export default class extends DebugPort {
516
479
  });
517
480
  }
518
481
 
482
+ gotoSource(objectId, prop) {
483
+ let object = this.sentObjects[objectId];
484
+ let value;
485
+
486
+ if (prop === null || prop === undefined) {
487
+ value = this.sentObjects[objectId];
488
+ } else {
489
+ value = calculateCP(object, { name: prop }, {});
490
+ }
491
+ // for functions and classes we want to show the source
492
+ if (typeof value === 'function') {
493
+ this.adapter.inspectValue(value);
494
+ }
495
+ // use typeOf to distinguish basic objects/classes and Date, Error etc.
496
+ // objects like {...} have the constructor set to Object
497
+ if (typeOf(value) === 'object' && value.constructor !== Object) {
498
+ this.adapter.inspectValue(value.constructor);
499
+ }
500
+ }
501
+
519
502
  sendToConsole(objectId, prop) {
520
503
  let object = this.sentObjects[objectId];
521
504
  let value;
@@ -675,7 +658,6 @@ export default class extends DebugPort {
675
658
  // insert ember mixins
676
659
  for (let mixin of own) {
677
660
  let name = (
678
- mixin[Ember.NAME_KEY] ||
679
661
  mixin.ownerConstructor ||
680
662
  emberNames.get(mixin) ||
681
663
  ''
@@ -722,7 +704,7 @@ export default class extends DebugPort {
722
704
  }
723
705
 
724
706
  if (
725
- object instanceof Ember.ArrayProxy &&
707
+ object instanceof ArrayProxy &&
726
708
  object.content &&
727
709
  !object._showProxyDetails
728
710
  ) {
@@ -941,7 +923,7 @@ function addProperties(properties, hash) {
941
923
  }
942
924
 
943
925
  if (!options.isService) {
944
- options.isService = desc.value instanceof Ember.Service;
926
+ options.isService = desc.value instanceof Service;
945
927
  }
946
928
  }
947
929
  if (options.isService) {
@@ -1117,7 +1099,8 @@ function calculateCPs(
1117
1099
  if (cache !== undefined || !item.isExpensive) {
1118
1100
  let value;
1119
1101
  if (item.canTrack && HAS_GLIMMER_TRACKING) {
1120
- const tagInfo = (tracked[item.name] = {});
1102
+ tracked[item.name] = tracked[item.name] || {};
1103
+ const tagInfo = tracked[item.name];
1121
1104
  tagInfo.tag = track(() => {
1122
1105
  value = calculateCP(object, item, errorsForObject);
1123
1106
  });
@@ -1272,7 +1255,7 @@ function getDebugInfo(object) {
1272
1255
  let debugInfo = null;
1273
1256
  let objectDebugInfo = object._debugInfo;
1274
1257
  if (objectDebugInfo && typeof objectDebugInfo === 'function') {
1275
- if (object instanceof Ember.ObjectProxy && object.content) {
1258
+ if (object instanceof ObjectProxy && object.content) {
1276
1259
  object = object.content;
1277
1260
  }
1278
1261
  debugInfo = objectDebugInfo.call(object);
@@ -1285,7 +1268,7 @@ function getDebugInfo(object) {
1285
1268
  skipProperties.push('isDestroyed', 'isDestroying', 'container');
1286
1269
  // 'currentState' and 'state' are un-observable private properties.
1287
1270
  // The rest are skipped to reduce noise in the inspector.
1288
- if (Ember.Component && object instanceof Ember.Component) {
1271
+ if (Component && object instanceof Component) {
1289
1272
  skipProperties.push(
1290
1273
  'currentState',
1291
1274
  'state',
@@ -1320,7 +1303,7 @@ function calculateCP(object, item, errorsForObject) {
1320
1303
  const property = item.name;
1321
1304
  delete errorsForObject[property];
1322
1305
  try {
1323
- if (object instanceof Ember.ArrayProxy && property == parseInt(property)) {
1306
+ if (object instanceof ArrayProxy && property == parseInt(property)) {
1324
1307
  return object.objectAt(property);
1325
1308
  }
1326
1309
  return item.isGetter || property.includes?.('.')
@@ -1,10 +1,9 @@
1
1
  /* eslint-disable ember/no-private-routing-service */
2
2
  import DebugPort from './debug-port';
3
3
  import { compareVersion } from 'ember-debug/utils/version';
4
+ import { VERSION } from 'ember-debug/utils/ember';
4
5
  import classify from 'ember-debug/utils/classify';
5
6
  import dasherize from 'ember-debug/utils/dasherize';
6
-
7
- import Ember from 'ember-debug/utils/ember';
8
7
  import { _backburner, later } from 'ember-debug/utils/ember/runloop';
9
8
  import bound from 'ember-debug/utils/bound-method';
10
9
 
@@ -202,7 +201,7 @@ function buildSubTree(routeTree, route) {
202
201
  // 3.9.0 removed intimate APIs from router
203
202
  // https://github.com/emberjs/ember.js/pull/17843
204
203
  // https://deprecations.emberjs.com/v3.x/#toc_remove-handler-infos
205
- if (compareVersion(Ember.VERSION, '3.9.0') !== -1) {
204
+ if (compareVersion(VERSION, '3.9.0') !== -1) {
206
205
  // Ember >= 3.9.0
207
206
  routeHandler = routerLib.getRoute(handler);
208
207
  } else {
@@ -9,6 +9,7 @@ try {
9
9
  }
10
10
 
11
11
  let {
12
+ ArrayProxy,
12
13
  Namespace,
13
14
  ActionHandler,
14
15
  ControllerMixin,
@@ -21,16 +22,25 @@ let {
21
22
  Observable,
22
23
  Evented,
23
24
  PromiseProxyMixin,
25
+ Service,
24
26
  Object: EmberObject,
27
+ ObjectProxy,
25
28
  VERSION,
26
29
  ComputedProperty,
27
30
  meta,
28
31
  get,
29
32
  set,
30
33
  computed,
34
+ _captureRenderTree: captureRenderTree,
31
35
  } = Ember || {};
32
36
 
37
+ let getEnv = () => Ember.ENV;
38
+
33
39
  if (!Ember) {
40
+ captureRenderTree = emberSafeRequire('@ember/debug')?.captureRenderTree;
41
+ getEnv = emberSafeRequire('@ember/-internals/environment')?.getENV;
42
+ ArrayProxy = emberSafeRequire('@ember/array/proxy')?.default;
43
+ ObjectProxy = emberSafeRequire('@ember/object/proxy')?.default;
34
44
  MutableArray = emberSafeRequire('@ember/array/mutable')?.default;
35
45
  Namespace = emberSafeRequire('@ember/application/namespace')?.default;
36
46
  MutableEnumerable = emberSafeRequire('@ember/enumerable/mutable')?.default;
@@ -44,6 +54,7 @@ if (!Ember) {
44
54
  PromiseProxyMixin = emberSafeRequire(
45
55
  '@ember/object/promise-proxy-mixin'
46
56
  )?.default;
57
+ Service = emberSafeRequire('@ember/service')?.default;
47
58
  EmberObject = emberSafeRequire('@ember/object')?.default;
48
59
  VERSION = emberSafeRequire('ember/version')?.default;
49
60
  ComputedProperty = emberSafeRequire(
@@ -55,6 +66,7 @@ if (!Ember) {
55
66
  }
56
67
 
57
68
  export {
69
+ ArrayProxy,
58
70
  Namespace,
59
71
  ActionHandler,
60
72
  Application,
@@ -63,9 +75,11 @@ export {
63
75
  MutableEnumerable,
64
76
  NativeArray,
65
77
  CoreObject,
78
+ ObjectProxy,
66
79
  Component,
67
80
  Observable,
68
81
  Evented,
82
+ Service,
69
83
  PromiseProxyMixin,
70
84
  EmberObject,
71
85
  VERSION,
@@ -74,6 +88,8 @@ export {
74
88
  computed,
75
89
  get,
76
90
  set,
91
+ captureRenderTree,
92
+ getEnv,
77
93
  };
78
94
 
79
95
  export default Ember;
@@ -7,6 +7,10 @@ export default function getObjectName(object) {
7
7
  (emberNames.get(object.constructor) || object.constructor.name)) ||
8
8
  '';
9
9
 
10
+ if (object instanceof Function) {
11
+ return 'Function ' + object.name;
12
+ }
13
+
10
14
  // check if object is a primitive value
11
15
  if (object !== Object(object)) {
12
16
  return typeof object;
@@ -12,7 +12,7 @@ export function modelName(model) {
12
12
  }
13
13
 
14
14
  if (name.length > 50) {
15
- name = `${name.substr(0, 50)}...`;
15
+ name = `${name.slice(0, 50)}...`;
16
16
  }
17
17
  return name;
18
18
  }
@@ -1,5 +1,9 @@
1
- import Debug from 'ember-debug/utils/ember/debug';
2
- import { ComputedProperty, meta as emberMeta } from 'ember-debug/utils/ember';
1
+ import Debug, { inspect as emberInspect } from 'ember-debug/utils/ember/debug';
2
+ import {
3
+ ComputedProperty,
4
+ EmberObject,
5
+ meta as emberMeta,
6
+ } from 'ember-debug/utils/ember';
3
7
  import { emberSafeRequire } from 'ember-debug/utils/ember/loader';
4
8
 
5
9
  /**
@@ -21,14 +25,6 @@ export function isComputed(object, key) {
21
25
  if (getDescriptorFor(object, key) instanceof ComputedProperty) {
22
26
  return true;
23
27
  }
24
-
25
- // Ember < 3.10
26
- return object[key] instanceof ComputedProperty;
27
- }
28
-
29
- export function isDescriptor(value) {
30
- // Ember >= 1.11
31
- return value && typeof value === 'object' && value.isDescriptor;
32
28
  }
33
29
 
34
30
  /**
@@ -38,11 +34,11 @@ export function isDescriptor(value) {
38
34
  * @param {String} key The key for the property on the object
39
35
  */
40
36
  export function getDescriptorFor(object, key) {
41
- if (isDescriptor(object[key])) {
37
+ if (object[key]?.isDescriptor) {
42
38
  return object[key];
43
39
  }
44
40
 
45
- // exists longeer than ember 3.10
41
+ // exists longer than ember 3.10
46
42
  if (Debug.isComputed) {
47
43
  const { descriptorForDecorator, descriptorForProperty } =
48
44
  emberSafeRequire('@ember/-internals/metal') || {};
@@ -61,3 +57,77 @@ export function typeOf(obj) {
61
57
  .match(/\s([a-zA-Z]+)/)[1]
62
58
  .toLowerCase();
63
59
  }
60
+
61
+ export function inspect(value) {
62
+ if (typeof value === 'function') {
63
+ return `${value.name || 'function'}() { ... }`;
64
+ } else if (value instanceof EmberObject) {
65
+ return value.toString();
66
+ } else if (value instanceof HTMLElement) {
67
+ return `<${value.tagName.toLowerCase()}>`;
68
+ } else if (typeOf(value) === 'array') {
69
+ if (value.length === 0) {
70
+ return '[]';
71
+ } else if (value.length === 1) {
72
+ return `[ ${inspect(value[0])} ]`;
73
+ } else {
74
+ return `[ ${inspect(value[0])}, ... ]`;
75
+ }
76
+ } else if (value instanceof Error) {
77
+ return `Error: ${value.message}`;
78
+ } else if (value === null) {
79
+ return 'null';
80
+ } else if (typeOf(value) === 'date') {
81
+ return value.toString();
82
+ } else if (typeof value === 'object') {
83
+ // `Ember.inspect` is able to handle this use case,
84
+ // but it is very slow as it loops over all props,
85
+ // so summarize to just first 2 props
86
+ // if it defines a toString, we use that instead
87
+ if (
88
+ typeof value.toString === 'function' &&
89
+ value.toString !== Object.prototype.toString &&
90
+ value.toString !== Function.prototype.toString
91
+ ) {
92
+ try {
93
+ return `<Object:${value.toString()}>`;
94
+ } catch (e) {
95
+ //
96
+ }
97
+ }
98
+ let ret = [];
99
+ let v;
100
+ let count = 0;
101
+ let broken = false;
102
+
103
+ for (let key in value) {
104
+ if (!('hasOwnProperty' in value) || value.hasOwnProperty(key)) {
105
+ if (count++ > 1) {
106
+ broken = true;
107
+ break;
108
+ }
109
+ v = value[key];
110
+ if (v === 'toString') {
111
+ continue;
112
+ } // ignore useless items
113
+ if (typeOf(v).includes('function')) {
114
+ v = `function ${v.name}() { ... }`;
115
+ }
116
+ if (typeOf(v) === 'array') {
117
+ v = `[Array : ${v.length}]`;
118
+ }
119
+ if (typeOf(v) === 'object') {
120
+ v = '[Object]';
121
+ }
122
+ ret.push(`${key}: ${v}`);
123
+ }
124
+ }
125
+ let suffix = ' }';
126
+ if (broken) {
127
+ suffix = ' ...}';
128
+ }
129
+ return `{ ${ret.join(', ')}${suffix}`;
130
+ } else {
131
+ return emberInspect(value);
132
+ }
133
+ }
@@ -23,6 +23,43 @@ export function compareVersion(version1, version2) {
23
23
  return 0;
24
24
  }
25
25
 
26
+ /**
27
+ *
28
+ * @param specifier e.g. ^5.12.0
29
+ * @param version 5.13
30
+ * @return {boolean}
31
+ */
32
+ export function isInVersionSpecifier(specifier, version) {
33
+ let compared, i, version2;
34
+ let operator = specifier[0];
35
+ if (Number.isNaN(+operator)) {
36
+ specifier = specifier.slice(1);
37
+ }
38
+ specifier = cleanupVersion(specifier).split('.');
39
+ version2 = cleanupVersion(version).split('.');
40
+ if (operator === '~' && specifier[1] !== version2[1]) {
41
+ return false;
42
+ }
43
+ if (operator === '^' && specifier[0] !== version2[0]) {
44
+ return false;
45
+ }
46
+
47
+ if (operator === '>' && specifier[0] > version2[0]) {
48
+ return false;
49
+ }
50
+
51
+ for (i = 0; i < 3; i++) {
52
+ compared = compare(+specifier[i], +version2[i]);
53
+ if (compared < 0) {
54
+ return true;
55
+ }
56
+ if (compared > 0) {
57
+ return false;
58
+ }
59
+ }
60
+ return true;
61
+ }
62
+
26
63
  /**
27
64
  * Remove -alpha, -beta, etc from versions
28
65
  *
@@ -132,7 +132,7 @@ export default class extends DebugPort {
132
132
  * @param {Node} node The DOM node to inspect
133
133
  */
134
134
  inspectNode(node) {
135
- this.adapter.inspectNode(node);
135
+ this.adapter.inspectValue(node);
136
136
  }
137
137
 
138
138
  sendTree(immediate = false) {
@@ -0,0 +1,30 @@
1
+ .goto-source {
2
+ background: none;
3
+ border: none;
4
+ border-bottom: 1px solid transparent;
5
+ color: var(--base15);
6
+ cursor: pointer;
7
+ margin: 0;
8
+ outline: none;
9
+ padding: 0;
10
+
11
+ svg {
12
+ vertical-align: middle;
13
+ }
14
+
15
+ .send-chevron {
16
+ fill: var(--focus);
17
+ }
18
+
19
+ .send-text {
20
+ fill: var(--base12);
21
+ }
22
+ }
23
+
24
+ .goto-source:hover {
25
+ border-bottom-color: var(--focus);
26
+ }
27
+
28
+ .goto-source:active {
29
+ transform: translateY(1px);
30
+ }
@@ -6,6 +6,7 @@
6
6
  @import 'nav';
7
7
  @import 'pill';
8
8
  @import 'send-to-console';
9
+ @import 'goto-source';
9
10
  @import 'object-inspector-toggle';
10
11
  @import 'split';
11
12
  @import 'toolbar/index';
@@ -17,6 +17,10 @@
17
17
  margin-left: 5px;
18
18
  margin-right: 5px;
19
19
  }
20
+ .toolbar .goto-source {
21
+ margin-left: 5px;
22
+ margin-right: 5px;
23
+ }
20
24
 
21
25
  @import 'checkbox';
22
26
  @import 'divider';