| 10 | } |
| 11 | |
| 12 | export class ScopeObserver implements ValueListObserverDelegate<Scope> { |
| 13 | readonly element: Element |
| 14 | readonly schema: Schema |
| 15 | private delegate: ScopeObserverDelegate |
| 16 | private valueListObserver: ValueListObserver<Scope> |
| 17 | private scopesByIdentifierByElement: WeakMap<Element, Map<string, Scope>> |
| 18 | private scopeReferenceCounts: WeakMap<Scope, number> |
| 19 | |
| 20 | constructor(element: Element, schema: Schema, delegate: ScopeObserverDelegate) { |
| 21 | this.element = element |
| 22 | this.schema = schema |
| 23 | this.delegate = delegate |
| 24 | this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this) |
| 25 | this.scopesByIdentifierByElement = new WeakMap() |
| 26 | this.scopeReferenceCounts = new WeakMap() |
| 27 | } |
| 28 | |
| 29 | start() { |
| 30 | this.valueListObserver.start() |
| 31 | } |
| 32 | |
| 33 | stop() { |
| 34 | this.valueListObserver.stop() |
| 35 | } |
| 36 | |
| 37 | get controllerAttribute() { |
| 38 | return this.schema.controllerAttribute |
| 39 | } |
| 40 | |
| 41 | // Value observer delegate |
| 42 | |
| 43 | parseValueForToken(token: Token): Scope | undefined { |
| 44 | const { element, content: identifier } = token |
| 45 | return this.parseValueForElementAndIdentifier(element, identifier) |
| 46 | } |
| 47 | |
| 48 | parseValueForElementAndIdentifier(element: Element, identifier: string): Scope | undefined { |
| 49 | const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element) |
| 50 | |
| 51 | let scope = scopesByIdentifier.get(identifier) |
| 52 | if (!scope) { |
| 53 | scope = this.delegate.createScopeForElementAndIdentifier(element, identifier) |
| 54 | scopesByIdentifier.set(identifier, scope) |
| 55 | } |
| 56 | |
| 57 | return scope |
| 58 | } |
| 59 | |
| 60 | elementMatchedValue(element: Element, value: Scope) { |
| 61 | const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1 |
| 62 | this.scopeReferenceCounts.set(value, referenceCount) |
| 63 | if (referenceCount == 1) { |
| 64 | this.delegate.scopeConnected(value) |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | elementUnmatchedValue(element: Element, value: Scope) { |
| 69 | const referenceCount = this.scopeReferenceCounts.get(value) |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…