-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19159 from emberjs/refactor/split-managers-into-m…
…ultiple-maps [REFACTOR] Split managers into multiple maps
- Loading branch information
Showing
7 changed files
with
152 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 0 additions & 40 deletions
40
packages/@ember/-internals/glimmer/lib/utils/custom-component-manager.ts
This file was deleted.
Oops, something went wrong.
15 changes: 0 additions & 15 deletions
15
packages/@ember/-internals/glimmer/lib/utils/custom-modifier-manager.ts
This file was deleted.
Oops, something went wrong.
140 changes: 125 additions & 15 deletions
140
packages/@ember/-internals/glimmer/lib/utils/managers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,144 @@ | ||
import { Owner } from '@ember/-internals/owner'; | ||
import { Option } from '@glimmer/interfaces'; | ||
import { deprecate } from '@ember/debug'; | ||
import { COMPONENT_MANAGER_STRING_LOOKUP } from '@ember/deprecated-features'; | ||
import { ManagerDelegate as ComponentManagerDelegate } from '../component-managers/custom'; | ||
import InternalComponentManager from '../component-managers/internal'; | ||
import { ModifierManagerDelegate } from '../modifiers/custom'; | ||
|
||
const MANAGERS: WeakMap<object, ManagerWrapper<unknown>> = new WeakMap(); | ||
type ManagerDelegate = | ||
| ComponentManagerDelegate<unknown> | ||
| InternalComponentManager | ||
| ModifierManagerDelegate<unknown>; | ||
|
||
const getPrototypeOf = Object.getPrototypeOf; | ||
const COMPONENT_MANAGERS = new WeakMap< | ||
object, | ||
ManagerFactory<ComponentManagerDelegate<unknown> | InternalComponentManager> | ||
>(); | ||
|
||
export type ManagerFactory<ManagerDelegate> = (owner: Owner) => ManagerDelegate; | ||
const MODIFIER_MANAGERS = new WeakMap<object, ManagerFactory<ModifierManagerDelegate<unknown>>>(); | ||
|
||
export interface ManagerWrapper<ManagerDelegate> { | ||
factory: ManagerFactory<ManagerDelegate>; | ||
internal: boolean; | ||
type: 'component' | 'modifier'; | ||
} | ||
const MANAGER_INSTANCES: WeakMap<Owner, WeakMap<ManagerFactory, unknown>> = new WeakMap(); | ||
|
||
export type ManagerFactory<D extends ManagerDelegate = ManagerDelegate> = (owner: Owner) => D; | ||
|
||
/////////// | ||
|
||
export function setManager<ManagerDelegate>(wrapper: ManagerWrapper<ManagerDelegate>, obj: object) { | ||
MANAGERS.set(obj, wrapper); | ||
const getPrototypeOf = Object.getPrototypeOf; | ||
|
||
function setManager<Def extends object>( | ||
map: WeakMap<object, ManagerFactory>, | ||
factory: ManagerFactory, | ||
obj: Def | ||
): Def { | ||
map.set(obj, factory); | ||
return obj; | ||
} | ||
|
||
export function getManager<ManagerDelegate>(obj: object): Option<ManagerWrapper<ManagerDelegate>> { | ||
function getManager<D extends ManagerDelegate>( | ||
map: WeakMap<object, ManagerFactory<D>>, | ||
obj: object | ||
): ManagerFactory<D> | undefined { | ||
let pointer = obj; | ||
while (pointer !== undefined && pointer !== null) { | ||
let manager = MANAGERS.get(pointer); | ||
const manager = map.get(pointer); | ||
|
||
if (manager !== undefined) { | ||
return manager as ManagerWrapper<ManagerDelegate>; | ||
return manager; | ||
} | ||
|
||
pointer = getPrototypeOf(pointer); | ||
} | ||
|
||
return null; | ||
return undefined; | ||
} | ||
|
||
function getManagerInstanceForOwner<D extends ManagerDelegate>( | ||
owner: Owner, | ||
factory: ManagerFactory<D> | ||
): D { | ||
let managers = MANAGER_INSTANCES.get(owner); | ||
|
||
if (managers === undefined) { | ||
managers = new WeakMap(); | ||
MANAGER_INSTANCES.set(owner, managers); | ||
} | ||
|
||
let instance = managers.get(factory); | ||
|
||
if (instance === undefined) { | ||
instance = factory(owner); | ||
managers.set(factory, instance!); | ||
} | ||
|
||
// We know for sure that it's the correct type at this point, but TS can't know | ||
return instance as D; | ||
} | ||
|
||
/////////// | ||
|
||
export function setModifierManager( | ||
factory: ManagerFactory<ModifierManagerDelegate<unknown>>, | ||
definition: object | ||
) { | ||
return setManager(MODIFIER_MANAGERS, factory, definition); | ||
} | ||
|
||
export function getModifierManager( | ||
owner: Owner, | ||
definition: object | ||
): ModifierManagerDelegate<unknown> | undefined { | ||
const factory = getManager(MODIFIER_MANAGERS, definition); | ||
|
||
if (factory !== undefined) { | ||
return getManagerInstanceForOwner(owner, factory); | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
export function setComponentManager( | ||
stringOrFunction: | ||
| string | ||
| ManagerFactory<ComponentManagerDelegate<unknown> | InternalComponentManager>, | ||
obj: object | ||
) { | ||
let factory: ManagerFactory<ComponentManagerDelegate<unknown> | InternalComponentManager>; | ||
if (COMPONENT_MANAGER_STRING_LOOKUP && typeof stringOrFunction === 'string') { | ||
deprecate( | ||
'Passing the name of the component manager to "setupComponentManager" is deprecated. Please pass a function that produces an instance of the manager.', | ||
false, | ||
{ | ||
id: 'deprecate-string-based-component-manager', | ||
until: '4.0.0', | ||
url: 'https://emberjs.com/deprecations/v3.x/#toc_component-manager-string-lookup', | ||
} | ||
); | ||
factory = function(owner: Owner) { | ||
return owner.lookup<ComponentManagerDelegate<unknown> | InternalComponentManager>( | ||
`component-manager:${stringOrFunction}` | ||
)!; | ||
}; | ||
} else { | ||
factory = stringOrFunction as ManagerFactory< | ||
ComponentManagerDelegate<unknown> | InternalComponentManager | ||
>; | ||
} | ||
|
||
return setManager(COMPONENT_MANAGERS, factory, obj); | ||
} | ||
|
||
export function getComponentManager( | ||
owner: Owner, | ||
definition: object | ||
): ComponentManagerDelegate<unknown> | InternalComponentManager | undefined { | ||
const factory = getManager<ComponentManagerDelegate<unknown> | InternalComponentManager>( | ||
COMPONENT_MANAGERS, | ||
definition | ||
); | ||
|
||
if (factory !== undefined) { | ||
return getManagerInstanceForOwner(owner, factory); | ||
} | ||
|
||
return undefined; | ||
} |