7
7
*/
8
8
9
9
import { Injector } from '../di' ;
10
- import { DirectiveDef } from '../render3' ;
11
10
import { assertDomNode } from '../render3/assert' ;
12
- import { getComponent , getInjector , getLocalRefs , loadContext } from '../render3/discovery_utils' ;
13
- import { TNode , TNodeFlags } from '../render3/interfaces/node' ;
11
+ import { getComponent , getContext , getInjectionTokens , getInjector , getListeners , getLocalRefs , isBrowserEvents , loadLContext , loadLContextFromNode } from '../render3/discovery_utils' ;
12
+ import { TNode } from '../render3/interfaces/node' ;
13
+ import { StylingIndex } from '../render3/interfaces/styling' ;
14
14
import { TVIEW } from '../render3/interfaces/view' ;
15
+ import { getProp , getValue , isClassBased } from '../render3/styling/class_and_style_bindings' ;
16
+ import { getStylingContext } from '../render3/styling/util' ;
15
17
import { DebugContext } from '../view/index' ;
16
18
17
19
export class EventListener {
@@ -204,54 +206,25 @@ class DebugNode__POST_R3__ implements DebugNode {
204
206
constructor ( nativeNode : Node ) { this . nativeNode = nativeNode ; }
205
207
206
208
get parent ( ) : DebugElement | null {
207
- const parent = this . nativeNode . parentNode as HTMLElement ;
209
+ const parent = this . nativeNode . parentNode as Element ;
208
210
return parent ? new DebugElement__POST_R3__ ( parent ) : null ;
209
211
}
210
212
211
213
get injector ( ) : Injector { return getInjector ( this . nativeNode ) ; }
212
214
213
215
get componentInstance ( ) : any {
214
216
const nativeElement = this . nativeNode ;
215
- return nativeElement && getComponent ( nativeElement as HTMLElement ) ;
216
- }
217
- get context ( ) : any {
218
- // https://angular-team.atlassian.net/browse/FW-719
219
- throw notImplemented ( ) ;
217
+ return nativeElement && getComponent ( nativeElement as Element ) ;
220
218
}
219
+ get context ( ) : any { return getContext ( this . nativeNode as Element ) ; }
221
220
222
221
get listeners ( ) : EventListener [ ] {
223
- // TODO: add real implementation;
224
- // https://angular-team.atlassian.net/browse/FW-719
225
- return [ ] ;
222
+ return getListeners ( this . nativeNode as Element ) . filter ( isBrowserEvents ) ;
226
223
}
227
224
228
225
get references ( ) : { [ key : string ] : any ; } { return getLocalRefs ( this . nativeNode ) ; }
229
226
230
- get providerTokens ( ) : any [ ] {
231
- // TODO move to discoverable utils
232
- const context = loadContext ( this . nativeNode as HTMLElement , false ) ! ;
233
- if ( ! context ) return [ ] ;
234
- const lView = context . lView ;
235
- const tView = lView [ TVIEW ] ;
236
- const tNode = tView . data [ context . nodeIndex ] as TNode ;
237
- const providerTokens : any [ ] = [ ] ;
238
- const nodeFlags = tNode . flags ;
239
- const startIndex = nodeFlags >> TNodeFlags . DirectiveStartingIndexShift ;
240
- const directiveCount = nodeFlags & TNodeFlags . DirectiveCountMask ;
241
- const endIndex = startIndex + directiveCount ;
242
- for ( let i = startIndex ; i < endIndex ; i ++ ) {
243
- let value = tView . data [ i ] ;
244
- if ( isDirectiveDefHack ( value ) ) {
245
- // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
246
- // design flaw. We should always store same type so that we can be monomorphic. The issue
247
- // is that for Components/Directives we store the def instead the type. The correct behavior
248
- // is that we should always be storing injectable type in this location.
249
- value = value . type ;
250
- }
251
- providerTokens . push ( value ) ;
252
- }
253
- return providerTokens ;
254
- }
227
+ get providerTokens ( ) : any [ ] { return getInjectionTokens ( this . nativeNode as Element ) ; }
255
228
}
256
229
257
230
class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugElement {
@@ -264,10 +237,10 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
264
237
return this . nativeNode . nodeType == Node . ELEMENT_NODE ? this . nativeNode as Element : null ;
265
238
}
266
239
267
- get name ( ) : string { return ( this . nativeElement as HTMLElement ) . nodeName ; }
240
+ get name ( ) : string { return this . nativeElement ! . nodeName ; }
268
241
269
242
get properties ( ) : { [ key : string ] : any ; } {
270
- const context = loadContext ( this . nativeNode ) ! ;
243
+ const context = loadLContext ( this . nativeNode ) ! ;
271
244
const lView = context . lView ;
272
245
const tView = lView [ TVIEW ] ;
273
246
const tNode = tView . data [ context . nodeIndex ] as TNode ;
@@ -278,18 +251,77 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
278
251
}
279
252
280
253
get attributes ( ) : { [ key : string ] : string | null ; } {
281
- // https://angular-team.atlassian.net/browse/FW-719
282
- throw notImplemented ( ) ;
254
+ const attributes : { [ key : string ] : string | null ; } = { } ;
255
+ const element = this . nativeElement ;
256
+ if ( element ) {
257
+ const eAttrs = element . attributes ;
258
+ for ( let i = 0 ; i < eAttrs . length ; i ++ ) {
259
+ const attr = eAttrs [ i ] ;
260
+ attributes [ attr . name ] = attr . value ;
261
+ }
262
+ }
263
+ return attributes ;
283
264
}
284
265
285
266
get classes ( ) : { [ key : string ] : boolean ; } {
286
- // https://angular-team.atlassian.net/browse/FW-719
287
- throw notImplemented ( ) ;
267
+ const classes : { [ key : string ] : boolean ; } = { } ;
268
+ const element = this . nativeElement ;
269
+ if ( element ) {
270
+ const lContext = loadLContextFromNode ( element ) ;
271
+ const lNode = lContext . lView [ lContext . nodeIndex ] ;
272
+ const stylingContext = getStylingContext ( lContext . nodeIndex , lContext . lView ) ;
273
+ if ( stylingContext ) {
274
+ for ( let i = StylingIndex . SingleStylesStartPosition ; i < lNode . length ;
275
+ i += StylingIndex . Size ) {
276
+ if ( isClassBased ( lNode , i ) ) {
277
+ const className = getProp ( lNode , i ) ;
278
+ const value = getValue ( lNode , i ) ;
279
+ if ( typeof value == 'boolean' ) {
280
+ // we want to ignore `null` since those don't overwrite the values.
281
+ classes [ className ] = value ;
282
+ }
283
+ }
284
+ }
285
+ } else {
286
+ // Fallback, just read DOM.
287
+ const eClasses = element . classList ;
288
+ for ( let i = 0 ; i < eClasses . length ; i ++ ) {
289
+ classes [ eClasses [ i ] ] = true ;
290
+ }
291
+ }
292
+ }
293
+ return classes ;
288
294
}
289
295
290
296
get styles ( ) : { [ key : string ] : string | null ; } {
291
- // https://angular-team.atlassian.net/browse/FW-719
292
- throw notImplemented ( ) ;
297
+ const styles : { [ key : string ] : string | null ; } = { } ;
298
+ const element = this . nativeElement ;
299
+ if ( element ) {
300
+ const lContext = loadLContextFromNode ( element ) ;
301
+ const lNode = lContext . lView [ lContext . nodeIndex ] ;
302
+ const stylingContext = getStylingContext ( lContext . nodeIndex , lContext . lView ) ;
303
+ if ( stylingContext ) {
304
+ for ( let i = StylingIndex . SingleStylesStartPosition ; i < lNode . length ;
305
+ i += StylingIndex . Size ) {
306
+ if ( ! isClassBased ( lNode , i ) ) {
307
+ const styleName = getProp ( lNode , i ) ;
308
+ const value = getValue ( lNode , i ) as string | null ;
309
+ if ( value !== null ) {
310
+ // we want to ignore `null` since those don't overwrite the values.
311
+ styles [ styleName ] = value ;
312
+ }
313
+ }
314
+ }
315
+ } else {
316
+ // Fallback, just read DOM.
317
+ const eStyles = ( element as HTMLElement ) . style ;
318
+ for ( let i = 0 ; i < eStyles . length ; i ++ ) {
319
+ const name = eStyles . item ( i ) ;
320
+ styles [ name ] = eStyles . getPropertyValue ( name ) ;
321
+ }
322
+ }
323
+ }
324
+ return styles ;
293
325
}
294
326
295
327
get childNodes ( ) : DebugNode [ ] {
@@ -332,24 +364,14 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme
332
364
}
333
365
334
366
triggerEventHandler ( eventName : string , eventObj : any ) : void {
335
- // This is a hack implementation. The correct implementation would bypass the DOM and `TNode`
336
- // information to invoke the listeners directly.
337
- // https://angular-team.atlassian.net/browse/FW-719
338
- const event = document . createEvent ( 'MouseEvent' ) ;
339
- event . initEvent ( eventName , true , true ) ;
340
- ( this . nativeElement as HTMLElement ) . dispatchEvent ( event ) ;
367
+ this . listeners . forEach ( ( listener ) => {
368
+ if ( listener . name === eventName ) {
369
+ listener . callback ( eventObj ) ;
370
+ }
371
+ } ) ;
341
372
}
342
373
}
343
374
344
- /**
345
- * This function should not exist because it is megamorphic and only mostly correct.
346
- *
347
- * See call site for more info.
348
- */
349
- function isDirectiveDefHack ( obj : any ) : obj is DirectiveDef < any > {
350
- return obj . type !== undefined && obj . template !== undefined && obj . declaredInputs !== undefined ;
351
- }
352
-
353
375
function _queryNodeChildrenR3 (
354
376
parentNode : DebugNode , predicate : Predicate < DebugNode > , matches : DebugNode [ ] ,
355
377
elementsOnly : boolean ) {
0 commit comments