Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/core/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export class Module {
readonly application: Application
readonly definition: Definition
private contextsByScope: WeakMap<Scope, Context>
private connectedContexts: Set<Context>
private connectedContextsByElement: Map<Element, Context>

constructor(application: Application, definition: Definition) {
this.application = application
this.definition = blessDefinition(definition)
this.contextsByScope = new WeakMap()
this.connectedContexts = new Set()
this.connectedContextsByElement = new Map()
}

get identifier(): string {
Expand All @@ -26,23 +26,27 @@ export class Module {
}

get contexts(): Context[] {
return Array.from(this.connectedContexts)
return Array.from(this.connectedContextsByElement.values())
}

connectContextForScope(scope: Scope) {
const context = this.fetchContextForScope(scope)
this.connectedContexts.add(context)
this.connectedContextsByElement.set(scope.element, context)
context.connect()
}

disconnectContextForScope(scope: Scope) {
const context = this.contextsByScope.get(scope)
if (context) {
this.connectedContexts.delete(context)
this.connectedContextsByElement.delete(scope.element)
context.disconnect()
}
}

getConnectedContextForElement(element: Element): Context | undefined {
return this.connectedContextsByElement.get(element)
}

private fetchContextForScope(scope: Scope): Context {
let context = this.contextsByScope.get(scope)
if (!context) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/outlet_observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export class OutletObserver implements AttributeObserverDelegate, SelectorObserv
}

private hasOutlet(element: Element, outletName: string) {
return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName)
return !!this.getOutlet(element, outletName) || this.outletElementsByName.has(outletName, element)
}

private getOutlet(element: Element, outletName: string) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class Router implements ScopeObserverDelegate {
getContextForElementAndIdentifier(element: Element, identifier: string) {
const module = this.modulesByIdentifier.get(identifier)
if (module) {
return module.contexts.find((context) => context.element == element)
return module.getConnectedContextForElement(element)
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/tests/modules/core/application_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ export default class ApplicationTests extends ApplicationTestCase {
this.assert.ok(this.controllers[0] instanceof BController)
}

"test finding a controller by its element does not list the contexts of its identifier"() {
this.application.load(this.definitions)
const module = this.application.router.modules.find((module) => module.identifier == "a")!
const contexts = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(module), "contexts")!.get!
let contextsReads = 0
Object.defineProperty(module, "contexts", {
configurable: true,
get() {
contextsReads++
return contexts.call(this)
},
})

const element = this.findElement(`[data-controller="a"]`)

this.assert.ok(this.application.getControllerForElementAndIdentifier(element, "a") instanceof AController)
this.assert.equal(contextsReads, 0)
}

get controllers() {
return this.application.controllers as LogController[]
}
Expand Down
14 changes: 14 additions & 0 deletions src/tests/modules/core/outlet_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ export default class OutletTests extends ControllerTestCase(OutletController) {
return ["test", "alpha", "beta", "gamma", "delta", "omega", "namespaced--epsilon"]
}

"test matching an element against an outlet selector does not list the connected outlets"() {
const { outletsByName } = (this.controller.context as any).outletObserver
const getValuesForKey = outletsByName.getValuesForKey
let outletsReads = 0
outletsByName.getValuesForKey = (outletName: string) => {
outletsReads++
return getValuesForKey.call(outletsByName, outletName)
}

this.controller.context.refresh()

this.assert.equal(outletsReads, 0)
}

"test OutletSet#find"() {
this.assert.equal(this.controller.outlets.find("alpha"), this.findElement("#alpha1"))
this.assert.equal(this.controller.outlets.find("beta"), this.findElement("#beta1"))
Expand Down