@@ -3,7 +3,7 @@ const { setTelemetry } = require('../utils/telemetry');
33
44const 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