-
-
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.
Implements the helper manager feature specified in RFC 625. Highlights: 1. Adds `getDebugName` to the interface for helper managers. This is an optional hook that is used for better logging purposes, and matches other internal APIs we've added recently. 2. `hasScheduledEffect` has not yet been implemented, and attempting to use it will cause an assertion to be thrown. Helper managers are not exposed with this PR, and the version passed to `helperCapabilities` is optimistic, but can be changed when we do expose them (along with an appropriate feature flag). Co-authored-by: Robert Jackson <me@rwjblue.com>
- Loading branch information
Showing
11 changed files
with
562 additions
and
90 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { assert } from '@ember/debug'; | ||
import { DEBUG } from '@glimmer/env'; | ||
import { Arguments, Helper as GlimmerHelper } from '@glimmer/interfaces'; | ||
import { createComputeRef, UNDEFINED_REFERENCE } from '@glimmer/reference'; | ||
import { argsProxyFor } from '../utils/args-proxy'; | ||
|
||
export type HelperDefinition = object; | ||
|
||
export interface HelperCapabilities { | ||
hasValue: boolean; | ||
hasDestroyable: boolean; | ||
hasScheduledEffect: boolean; | ||
} | ||
|
||
export function helperCapabilities( | ||
managerAPI: string, | ||
options: Partial<HelperCapabilities> = {} | ||
): HelperCapabilities { | ||
assert('Invalid helper manager compatibility specified', managerAPI === '3.23'); | ||
|
||
assert( | ||
'You must pass either the `hasValue` OR the `hasScheduledEffect` capability when defining a helper manager. Passing neither, or both, is not permitted.', | ||
(options.hasValue || options.hasScheduledEffect) && | ||
!(options.hasValue && options.hasScheduledEffect) | ||
); | ||
|
||
assert( | ||
'The `hasScheduledEffect` capability has not yet been implemented for helper managers. Please pass `hasValue` instead', | ||
!options.hasScheduledEffect | ||
); | ||
|
||
return { | ||
hasValue: Boolean(options.hasValue), | ||
hasDestroyable: Boolean(options.hasDestroyable), | ||
hasScheduledEffect: Boolean(options.hasScheduledEffect), | ||
}; | ||
} | ||
|
||
export interface HelperManager<HelperStateBucket = unknown> { | ||
capabilities: HelperCapabilities; | ||
|
||
createHelper(definition: HelperDefinition, args: Arguments): HelperStateBucket; | ||
|
||
getDebugName?(definition: HelperDefinition): string; | ||
} | ||
|
||
export interface HelperManagerWithValue<HelperStateBucket = unknown> | ||
extends HelperManager<HelperStateBucket> { | ||
getValue(bucket: HelperStateBucket): unknown; | ||
} | ||
|
||
function hasValue(manager: HelperManager): manager is HelperManagerWithValue { | ||
return manager.capabilities.hasValue; | ||
} | ||
|
||
export interface HelperManagerWithDestroyable<HelperStateBucket = unknown> | ||
extends HelperManager<HelperStateBucket> { | ||
getDestroyable(bucket: HelperStateBucket): object; | ||
} | ||
|
||
function hasDestroyable(manager: HelperManager): manager is HelperManagerWithDestroyable { | ||
return manager.capabilities.hasDestroyable; | ||
} | ||
|
||
export default function customHelper( | ||
manager: HelperManager<unknown>, | ||
definition: HelperDefinition | ||
): GlimmerHelper { | ||
return (args, vm) => { | ||
const bucket = manager.createHelper(definition, argsProxyFor(args.capture(), 'helper')); | ||
|
||
if (hasDestroyable(manager)) { | ||
vm.associateDestroyable(manager.getDestroyable(bucket)); | ||
} | ||
|
||
if (hasValue(manager)) { | ||
return createComputeRef( | ||
() => manager.getValue(bucket), | ||
null, | ||
DEBUG && manager.getDebugName && manager.getDebugName(definition) | ||
); | ||
} else { | ||
return UNDEFINED_REFERENCE; | ||
} | ||
}; | ||
} |
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
Oops, something went wrong.