-
Notifications
You must be signed in to change notification settings - Fork 75
/
ember-component-manager.ts
134 lines (111 loc) · 3.68 KB
/
ember-component-manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { DEBUG } from '@glimmer/env';
import Ember from 'ember';
import { set } from '@ember/object';
import { getOwner, setOwner } from '@ember/application';
import { capabilities } from '@ember/component';
import { schedule } from '@ember/runloop';
import { gte } from 'ember-compatibility-helpers';
import BaseComponentManager, {
ComponentManagerArgs,
CustomComponentCapabilities,
} from './base-component-manager';
import GlimmerComponent, { Constructor } from './component';
import { setDestroyed, setDestroying } from './destroyables';
const CAPABILITIES = gte('3.13.0-beta.1')
? capabilities('3.13', {
destructor: true,
asyncLifecycleCallbacks: false,
updateHook: false,
})
: capabilities('3.4', {
destructor: true,
asyncLifecycleCallbacks: false,
});
const scheduledDestroyComponent = gte('3.20.0-beta.4')
? undefined
: (component: GlimmerComponent, meta: EmberMeta) => {
if (component.isDestroyed) {
return;
}
Ember.destroy(component);
meta.setSourceDestroyed();
setDestroyed(component);
};
const destroy = gte('3.20.0-beta.4')
// @ts-ignore
? Ember.__loader.require('@glimmer/runtime').destroy
: (component: GlimmerComponent) => {
if (component.isDestroying) {
return;
}
let meta = Ember.meta(component);
meta.setSourceDestroying();
setDestroying(component);
schedule('actions', component, component.willDestroy);
schedule('destroy', this, scheduledDestroyComponent, component, meta);
};
const registerDestructor = gte('3.20.0-beta.4')
// @ts-ignore
? Ember.__loader.require('@glimmer/runtime').registerDestructor
: undefined;
/**
* This component manager runs in Ember.js environments and extends the base component manager to:
*
* 1. Properly destroy the component's associated `meta` data structure
* 2. Schedule destruction using Ember's runloop
*/
class EmberGlimmerComponentManager extends BaseComponentManager(setOwner, getOwner, CAPABILITIES) {
createComponent(
ComponentClass: Constructor<GlimmerComponent>,
args: ComponentManagerArgs
): GlimmerComponent {
const component = super.createComponent(ComponentClass, args);
if (gte('3.20.0-beta.4')) {
registerDestructor(component, () => {
component.willDestroy();
});
}
return component;
}
destroyComponent(component: GlimmerComponent) {
destroy(component);
}
}
interface EmberGlimmerComponentManager {
updateComponent?: (component: GlimmerComponent, args: ComponentManagerArgs) => void;
}
// In Ember 3.12 and earlier, the updateComponent hook was mandatory.
// As of Ember 3.13, the `args` object is stable and each property of the
// object participates in the autotrack stack on its own. This means we do not
// need to set the `args` property on the component instance to invalidate
// tracked getters that rely on `args`, and therefore don't require the `updateComponent`
// hook at all.
if (!gte('3.13.0-beta.1')) {
EmberGlimmerComponentManager.prototype.updateComponent = function updateComponent(
component: GlimmerComponent,
args: ComponentManagerArgs
) {
let argSnapshot = args.named;
if (DEBUG) {
argSnapshot = Object.freeze(argSnapshot);
}
set(component, 'args', argSnapshot);
};
}
export default EmberGlimmerComponentManager;
interface EmberMeta {
setSourceDestroying(): void;
setSourceDestroyed(): void;
}
declare module 'ember' {
export namespace Ember {
function destroy(obj: {}): void;
function meta(obj: {}): EmberMeta;
}
}
declare module '@ember/component' {
export function capabilities(
version: '3.13' | '3.4',
capabilities: Partial<CustomComponentCapabilities>
): CustomComponentCapabilities;
}