Skip to content

Commit 2880c33

Browse files
initial refactor
1 parent 13265ca commit 2880c33

3 files changed

Lines changed: 213 additions & 223 deletions

File tree

lib/gather/gather-telemetry.js

Lines changed: 13 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const { setTelemetry } = require('../utils/telemetry');
33

44
const DEFAULT_PUPPETEER_ARGS = { ignoreHTTPSErrors: true };
55

6-
module.exports = async function gatherTelemetry(url, puppeteerArgs = {}) {
6+
module.exports = async function gatherTelemetry(url, gatherFn, puppeteerArgs = {}) {
77
Object.assign(puppeteerArgs, DEFAULT_PUPPETEER_ARGS);
88

99
const browser = await puppeteer.launch(puppeteerArgs);
@@ -15,11 +15,12 @@ module.exports = async function gatherTelemetry(url, puppeteerArgs = {}) {
1515
console.error(message); // eslint-disable-line no-console
1616
});
1717

18-
// Get the "viewport" of the page, as reported by the page.
18+
await page.exposeFunction('gatherFn', gatherFn);
19+
1920
const telemetry = await page.evaluate(() => {
2021
const SKIPPED_MODULES = ['fetch/ajax'];
2122

22-
/* globals window, Ember */
23+
/* globals window,*/
2324
let telemetry = {};
2425

2526
const modules = Object.keys(window.require.entries);
@@ -28,235 +29,24 @@ module.exports = async function gatherTelemetry(url, puppeteerArgs = {}) {
2829
if (SKIPPED_MODULES.includes(modulePath)) {
2930
continue;
3031
}
32+
if (window.gatherFn && typeof window.gatherFn === 'function') {
33+
try {
34+
let module = require(modulePath);
3135

32-
try {
33-
let module = require(modulePath);
34-
35-
if (module && module.default && module.default.proto) {
36-
let defaultProto = module.default.proto();
37-
38-
telemetry[modulePath] = parseMeta(Ember.meta(defaultProto));
39-
}
40-
} catch (error) {
41-
// log the error, but continue
42-
window.logErrorInNodeProcess(`error evaluating \`${modulePath}\`: ${error.message}`);
43-
}
44-
}
45-
46-
/**
47-
* Compares the object with types of Ember objects
48-
*
49-
* @param {Object} object
50-
* @returns {String} type
51-
*/
52-
function getType(object) {
53-
const types = [
54-
'Application',
55-
'Controller',
56-
'Route',
57-
'Component',
58-
'Service',
59-
'Helper',
60-
'Router',
61-
'Engine',
62-
];
63-
return types.find(type => Ember[type] && object instanceof Ember[type]) || 'EmberObject';
64-
}
65-
66-
/**
67-
* Parses ember meta data object and collects the runtime information
68-
*
69-
* @param {Object} meta
70-
* @returns {Object} data - Parsed metadata for the ember object
71-
* @returns {String[]} data.computedProperties - list of computed properties
72-
* @returns {String[]} data.getters - list of ES5 getters
73-
* @returns {String[]} data.observedProperties - list of observed properties
74-
* @returns {Object} data.observerProperties - list of observer properties
75-
* @returns {Object} data.offProperties - list of observer properties
76-
* @returns {String[]} data.overriddenActions - list of overridden actions
77-
* @returns {String[]} data.overriddenProperties - list of overridden properties
78-
* @returns {String[]} data.ownProperties - list of object's own properties
79-
* @returns {String} data.type - type of ember object
80-
* @returns {Object} data.unobservedProperties - list of unobserved properties
81-
*/
82-
function parseMeta(meta = {}) {
83-
if (!meta || !meta.source) {
84-
return {};
85-
}
86-
const { source } = meta;
87-
const type = getType(source);
88-
89-
const ownProperties = Object.keys(source).filter(key => !['_super', 'actions'].includes(key));
36+
if (module && module.default && module.default.proto) {
37+
let defaultProto = module.default.proto();
9038

91-
const ownActions = source.actions ? Object.keys(source.actions) : [];
92-
93-
const observedProperties = Object.keys(meta._watching || {});
94-
95-
const overriddenProperties = ownProperties.filter(key => isOverridden(meta.parent, key));
96-
97-
const overriddenActions = ownActions.filter(key => isActionOverridden(meta.parent, key));
98-
99-
const computedProperties = [];
100-
meta.forEachDescriptors((name, desc) => {
101-
const descProto = Object.getPrototypeOf(desc) || {};
102-
const constructorName = descProto.constructor ? descProto.constructor.name : '';
103-
if (
104-
desc.enumerable &&
105-
ownProperties.includes(name) &&
106-
constructorName === 'ComputedProperty'
107-
) {
108-
computedProperties.push(name);
109-
}
110-
});
111-
112-
const ownDesc = Object.getOwnPropertyDescriptors(source);
113-
const getters = Object.keys(ownDesc).filter(
114-
key => ownDesc[key].get && !computedProperties.includes(key)
115-
);
116-
117-
const { offProperties, unobservedProperties } = ownProperties.reduce(
118-
({ offProperties, unobservedProperties }, key) => {
119-
const { type, events } = getListenerData(meta.parent, key);
120-
if (type === 'event') {
121-
offProperties[key] = events;
122-
} else if (type === 'observer') {
123-
unobservedProperties[key] = events;
39+
telemetry[modulePath] = window.gatherFn(defaultProto);
12440
}
125-
return { offProperties, unobservedProperties };
126-
},
127-
{
128-
offProperties: {},
129-
unobservedProperties: {},
41+
} catch (error) {
42+
// log the error, but continue
43+
window.logErrorInNodeProcess(`error evaluating \`${modulePath}\`: ${error.message}`);
13044
}
131-
);
132-
133-
const observerProperties = observedProperties.reduce((acc, oProp) => {
134-
const listenerData = meta.matchingListeners(`${oProp}:change`);
135-
if (listenerData) {
136-
const listener = listenerData[1];
137-
acc[listener] = [].concat(acc[listener] || [], [oProp]);
138-
}
139-
return acc;
140-
}, {});
141-
142-
return {
143-
computedProperties,
144-
getters,
145-
observedProperties,
146-
observerProperties,
147-
offProperties,
148-
overriddenActions,
149-
overriddenProperties,
150-
ownProperties,
151-
type,
152-
unobservedProperties,
153-
};
154-
}
155-
156-
/**
157-
* Parses the ember meta with passed key
158-
*
159-
* @param {Ember.meta} map
160-
* @param {String} key
161-
* @returns {Object} meta - The listener meta data
162-
* @returns {String} meta.type - Type of listener can be observer|event
163-
* @returns {String[]} meta.events - name of events/properties the listener is registered on
164-
*/
165-
function getListenerData(map, key) {
166-
while (map) {
167-
let type = 'event';
168-
const events = parseListeners(map._listeners).reduce((acc, [event, , method]) => {
169-
if (method === key) {
170-
const [observedProp, observerEvent] = event.split(':');
171-
if (observerEvent) {
172-
type = 'observer';
173-
}
174-
acc.push(observedProp);
175-
}
176-
return acc;
177-
}, []);
178-
if (events.length) {
179-
return {
180-
type,
181-
events,
182-
};
183-
}
184-
map = map.parent;
185-
}
186-
return {};
187-
}
188-
189-
/**
190-
* Parse the listeners to a group of array of 4 elements
191-
*
192-
* @param {Array} listeners
193-
* @param {int} size
194-
* @returns Array
195-
*/
196-
function parseListeners(listeners = [], size = 4) {
197-
var result = [];
198-
if (listeners.length) {
199-
if (typeof listeners[0] === 'object') {
200-
result = listeners.map(({ event, target, method, kind }) => [
201-
event,
202-
target,
203-
method,
204-
kind,
205-
]);
206-
} else {
207-
const input = listeners.slice(0);
208-
while (input.length) {
209-
result.push(input.splice(0, size));
210-
}
211-
}
212-
}
213-
return result;
214-
}
215-
216-
/**
217-
* Checks if passed key is overriding any value from the parent objects
218-
*
219-
* @param {Object} map
220-
* @param {String} key
221-
* @returns boolean
222-
*/
223-
function isOverridden(map, key) {
224-
while (map) {
225-
const value = map.peekValues ? map.peekValues(key) : undefined;
226-
if (value !== undefined || (map.source && key in map.source)) {
227-
return true;
228-
}
229-
map = map.parent;
230-
}
231-
return false;
232-
}
233-
234-
/**
235-
* Checks if passed key is overriding any value from the parent objects' actions
236-
*
237-
* @param {Object} map
238-
* @param {String} key
239-
* @returns boolean
240-
*/
241-
function isActionOverridden(map, key) {
242-
while (map) {
243-
const { source } = map;
244-
if (source) {
245-
const { actions } = source;
246-
const value = actions ? actions[key] : undefined;
247-
if (value !== undefined) {
248-
return true;
249-
}
250-
}
251-
map = map.parent;
25245
}
253-
return false;
25446
}
255-
25647
return telemetry;
25748
});
25849

25950
setTelemetry(telemetry);
260-
26151
await browser.close();
26252
};

0 commit comments

Comments
 (0)