-
Notifications
You must be signed in to change notification settings - Fork 794
/
initialize-component.ts
124 lines (111 loc) · 4.98 KB
/
initialize-component.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
import * as d from '../declarations';
import { BUILD } from '@app-data';
import { consoleError, loadModule, styles } from '@platform';
import { CMP_FLAGS, HOST_FLAGS } from '@utils';
import { proxyComponent } from './proxy-component';
import { safeCall, scheduleUpdate } from './update-component';
import { computeMode } from './mode';
import { getScopeId, registerStyle } from './styles';
import { PROXY_FLAGS } from './runtime-constants';
import { createTime, uniqueTime } from './profile';
export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef, cmpMeta: d.ComponentRuntimeMeta, hmrVersionId?: string, Cstr?: any) => {
// initializeComponent
if ((BUILD.lazyLoad || BUILD.hydrateServerSide || BUILD.style) && (hostRef.$flags$ & HOST_FLAGS.hasInitializedComponent) === 0) {
// we haven't initialized this element yet
hostRef.$flags$ |= HOST_FLAGS.hasInitializedComponent;
if (BUILD.mode && hostRef.$modeName$ == null) {
// initializeComponent
// looks like mode wasn't set as a property directly yet
// first check if there's an attribute
// next check the app's global
hostRef.$modeName$ = typeof cmpMeta.$lazyBundleIds$ !== 'string' ? computeMode(elm) : '';
}
if (BUILD.hydrateServerSide && hostRef.$modeName$) {
elm.setAttribute('s-mode', hostRef.$modeName$);
}
if (BUILD.lazyLoad || BUILD.hydrateClientSide) {
// lazy loaded components
// request the component's implementation to be
// wired up with the host element
Cstr = loadModule(cmpMeta, hostRef, hmrVersionId);
if (Cstr.then) {
// Await creates a micro-task avoid if possible
const endLoad = uniqueTime(`st:load:${cmpMeta.$tagName$}:${hostRef.$modeName$}`, `[Stencil] Load module for <${cmpMeta.$tagName$}>`);
Cstr = await Cstr;
endLoad();
}
if ((BUILD.isDev || BUILD.isDebug) && !Cstr) {
throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
}
if (BUILD.member && !Cstr.isProxied) {
// we'eve never proxied this Constructor before
// let's add the getters/setters to its prototype before
// the first time we create an instance of the implementation
if (BUILD.watchCallback) {
cmpMeta.$watchers$ = Cstr.watchers;
}
proxyComponent(Cstr, cmpMeta, PROXY_FLAGS.proxyState);
Cstr.isProxied = true;
}
const endNewInstance = createTime('createInstance', cmpMeta.$tagName$);
// ok, time to construct the instance
// but let's keep track of when we start and stop
// so that the getters/setters don't incorrectly step on data
if (BUILD.member) {
hostRef.$flags$ |= HOST_FLAGS.isConstructingInstance;
}
// construct the lazy-loaded component implementation
// passing the hostRef is very important during
// construction in order to directly wire together the
// host element and the lazy-loaded instance
try {
new (Cstr as any)(hostRef);
} catch (e) {
consoleError(e);
}
if (BUILD.member) {
hostRef.$flags$ &= ~HOST_FLAGS.isConstructingInstance;
}
if (BUILD.watchCallback) {
hostRef.$flags$ |= HOST_FLAGS.isWatchReady;
}
endNewInstance();
fireConnectedCallback(hostRef.$lazyInstance$);
} else {
Cstr = elm.constructor as any;
}
const scopeId = getScopeId(cmpMeta, hostRef.$modeName$);
if (BUILD.style && !styles.has(scopeId) && Cstr.style) {
const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
// this component has styles but we haven't registered them yet
let style = Cstr.style;
if (BUILD.mode && typeof style !== 'string') {
style = style[hostRef.$modeName$];
}
if (!BUILD.hydrateServerSide && BUILD.shadowDom && BUILD.shadowDomShim && cmpMeta.$flags$ & CMP_FLAGS.needsShadowDomShim) {
style = await import('../utils/shadow-css').then(m => m.scopeCss(style, scopeId, false));
}
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation));
endRegisterStyles();
}
}
// we've successfully created a lazy instance
const ancestorComponent = hostRef.$ancestorComponent$;
const schedule = () => scheduleUpdate(hostRef, true);
if (BUILD.asyncLoading && ancestorComponent && ancestorComponent['s-rc']) {
// this is the intial load and this component it has an ancestor component
// but the ancestor component has NOT fired its will update lifecycle yet
// so let's just cool our jets and wait for the ancestor to continue first
// this will get fired off when the ancestor component
// finally gets around to rendering its lazy self
// fire off the initial update
ancestorComponent['s-rc'].push(schedule);
} else {
schedule();
}
};
export const fireConnectedCallback = (instance: any) => {
if (BUILD.lazyLoad && BUILD.connectedCallback) {
safeCall(instance, 'connectedCallback');
}
};