@lwrjs/client-modules 0.17.2-alpha.3 → 0.17.2-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- const e=[];let o;const n=globalThis.LWR;n.define||n.env?globalThis.LWR=Object.freeze({define:n.define,env:n.env}):delete globalThis.LWR;const t={addLoaderPlugin:()=>{console.warn("API is not supported in ESM format")},handleStaleModule:function(n){e.push(n),o||(o=new WebSocket(`ws://${location.host}`),o.addEventListener("message",(async({data:o})=>{const n=JSON.parse(o);if("moduleUpdate"===n.eventType){const{oldHash:o,newHash:t,module:{specifier:a}}=n.payload;for(let n=0;n<e.length;n++){if(null!==(0,e[n])({name:a,oldHash:o,newHash:t}))break}}})))},appMetadata:function(){const{appId:e,bootstrapModule:o,rootComponent:t,rootComponents:a}=n;return{appId:e,bootstrapModule:o,rootComponent:t,rootComponents:a}}(),addServerDataCallback:function(e){}};export{t as services};
1
+ const e=[];let o;const n=globalThis,t=n.LWR;t.define||t.env?n.LWR=Object.freeze({define:t.define,env:t.env}):delete n.LWR;const a={addLoaderPlugin:()=>{console.warn("API is not supported in ESM format")},handleStaleModule:function(n){e.push(n),o||(o=new WebSocket(`ws://${location.host}`),o.addEventListener("message",(async o=>{const n=o.data,t=JSON.parse(n);if("moduleUpdate"===t.eventType){const{oldHash:o,newHash:n,module:{specifier:a}}=t.payload;for(let t=0;t<e.length;t++){if(null!==(0,e[t])({name:a,oldHash:o,newHash:n}))break}}})))},appMetadata:function(){const{appId:e,bootstrapModule:o,rootComponent:n,rootComponents:a}=t;return{appId:e,bootstrapModule:o,rootComponent:n,rootComponents:a}}(),addServerDataCallback:function(e){}};export{a as services};
2
2
  //# sourceMappingURL=servicesESM.js.map
@@ -1,26 +1,38 @@
1
1
  import { BOOTSTRAP_END, INIT, INIT_MODULE } from 'lwr/metrics';
2
2
  import { logOperationStart, logOperationEnd } from 'lwr/profiler';
3
3
  // TODO: This is a temporal workaround until https://github.com/salesforce/lwc/pull/2083 is sorted - tmp
4
+ // eslint-disable-next-line lwr/only-allowed-imports
4
5
  import { createElement } from 'lwc';
5
6
  // <hydrateComponentProxy> - This code is removed in core
6
7
  // Note: a build step uses these comments to strip the code for core.
8
+ // eslint-disable-next-line lwr/only-allowed-imports
7
9
  import { hydrateComponent } from 'lwc';
8
10
  function hydrateComponentProxy(customElement, Ctor, props) {
9
11
  hydrateComponent(customElement, Ctor, props);
10
12
  }
11
13
  // </hydrateComponentProxy>
12
- // Break up hydration tasks into timed batches.
13
- // Borrowed from https://tinyurl.com/5b4fw7eb
14
- const HYDRATION_TASK_BATCH_DURATION = 50;
15
- let timeOfLastYield = performance.now();
16
- function shouldYield() {
17
- const now = performance.now();
18
- if (now - timeOfLastYield > HYDRATION_TASK_BATCH_DURATION) {
19
- timeOfLastYield = now;
20
- return true;
14
+ const shouldYield = (() => {
15
+ const globalThisLWR = globalThis;
16
+ const { SSREnabled } = (globalThisLWR.LWR && globalThisLWR.LWR.env) || {};
17
+ // eslint-disable-next-line lwr/no-unguarded-apis
18
+ if (!globalThis.performance || !SSREnabled) {
19
+ return () => false;
21
20
  }
22
- return false;
23
- }
21
+ // Break up hydration tasks into timed batches.
22
+ // Borrowed from https://tinyurl.com/5b4fw7eb
23
+ const TASK_BATCH_DURATION = 50;
24
+ // eslint-disable-next-line lwr/no-unguarded-apis
25
+ let timeOfLastYield = globalThis.performance.now();
26
+ return () => {
27
+ // eslint-disable-next-line lwr/no-unguarded-apis
28
+ const now = globalThis.performance.now();
29
+ if (now - timeOfLastYield > TASK_BATCH_DURATION) {
30
+ timeOfLastYield = now;
31
+ return true;
32
+ }
33
+ return false;
34
+ };
35
+ })();
24
36
  function initializeWebComponent(elementName, Ctor) {
25
37
  return createElement(elementName, { is: Ctor });
26
38
  }
@@ -56,84 +68,97 @@ export function getPropFromAttrName(propName) {
56
68
  * @example - [['x/appRoot', appCtor], ['x/nav', navCtor]]
57
69
  */
58
70
  export function init(rootModules, serverData = {}) {
59
- if (typeof customElements === 'undefined' || typeof document === 'undefined') {
71
+ // eslint-disable-next-line lwr/no-unguarded-apis
72
+ if (typeof globalThis.customElements === 'undefined' || typeof globalThis.document === 'undefined') {
60
73
  logOperationStart({ id: BOOTSTRAP_END });
61
74
  return;
62
75
  }
63
76
  logOperationStart({ id: INIT });
64
- let index = 0;
65
- for (const [specifier, ctor] of rootModules) {
66
- const elementName = toKebabCase(specifier);
67
- // initialize and inject the root module into the LWR Root or DOM if it is missing
68
- if (!document.body.querySelector(elementName)) {
69
- logOperationStart({ id: INIT_MODULE, specifier, specifierIndex: ++index });
70
- // this is for SPA like routes (one component at the root level) utilizing the lwr-root directive
71
- const component = initializeWebComponent(elementName, ctor);
72
- const container = document.querySelector('[lwr-root]');
73
- container ? container.appendChild(component) : document.body.appendChild(component);
74
- logOperationEnd({
75
- id: INIT_MODULE,
76
- specifier,
77
- specifierIndex: index,
78
- metadata: { renderMode: 'spa' },
79
- });
80
- continue;
81
- }
82
- // the page has been rendered or SSR'd, and each component needs to initialized(or hydrated)
83
- const elements = document.querySelectorAll(elementName);
84
- for (const element of elements) {
85
- logOperationStart({ id: INIT_MODULE, specifier, specifierIndex: ++index });
86
- const propsId = element.dataset.lwrPropsId;
87
- // hydrate SSR'd components
88
- if (propsId) {
89
- if (shouldYield()) {
90
- // give room for the browser to render during long hydration tasks
91
- setTimeout(() => {
92
- hydrateComponentProxy(element, ctor, serverData[propsId] || {});
93
- }, 0);
94
- }
95
- else {
96
- hydrateComponentProxy(element, ctor, serverData[propsId] || {});
97
- }
77
+ (async () => {
78
+ let index = 0;
79
+ // eslint-disable-next-line lwr/no-unguarded-apis
80
+ const document = globalThis.document;
81
+ for (const [specifier, ctor] of rootModules) {
82
+ if (shouldYield()) {
83
+ // Yield to the main thread during long hydration tasks
84
+ // eslint-disable-next-line no-await-in-loop
85
+ await yieldToMainThread();
86
+ }
87
+ const specifierIndex = ++index;
88
+ const elementName = toKebabCase(specifier);
89
+ // initialize and inject the root module into the LWR Root or DOM if it is missing
90
+ // eslint-disable-next-line lwr/no-unguarded-apis
91
+ if (!document.body.querySelector(elementName)) {
92
+ logOperationStart({ id: INIT_MODULE, specifier, specifierIndex });
93
+ // this is for SPA like routes (one component at the root level) utilizing the lwr-root directive
94
+ const component = initializeWebComponent(elementName, ctor);
95
+ // eslint-disable-next-line lwr/no-unguarded-apis
96
+ const container = document.querySelector('[lwr-root]');
97
+ // eslint-disable-next-line lwr/no-unguarded-apis
98
+ container ? container.appendChild(component) : document.body.appendChild(component);
98
99
  logOperationEnd({
99
100
  id: INIT_MODULE,
100
101
  specifier,
101
- specifierIndex: index,
102
- metadata: { renderMode: 'ssr' },
102
+ specifierIndex,
103
+ metadata: { renderMode: 'spa' },
103
104
  });
104
105
  continue;
105
106
  }
106
- // Note: due to the bug described at the top of this file, each CSR'd custom element
107
- // must be replaced with the new synthetic constructor. Attributes and children are
108
- // copied over to the new component.
109
- const component = initializeWebComponent(elementName, ctor);
110
- // copy the attributes
111
- for (const { name, value } of element.attributes) {
112
- component.setAttribute(name, value);
113
- const prop = getPropFromAttrName(name);
114
- if (prop in component) {
115
- // set attributes as properties for reactivity
116
- component[prop] = value;
107
+ // the page has been rendered or SSR'd, and each component needs to initialized(or hydrated)
108
+ // eslint-disable-next-line lwr/no-unguarded-apis
109
+ const elements = document.querySelectorAll(elementName);
110
+ for (const element of elements) {
111
+ logOperationStart({ id: INIT_MODULE, specifier, specifierIndex });
112
+ const propsId = element.dataset.lwrPropsId;
113
+ // hydrate SSR'd components
114
+ if (propsId) {
115
+ hydrateComponentProxy(element, ctor, serverData[propsId] || {});
116
+ logOperationEnd({
117
+ id: INIT_MODULE,
118
+ specifier,
119
+ specifierIndex,
120
+ metadata: { renderMode: 'ssr' },
121
+ });
122
+ continue;
117
123
  }
124
+ // Note: due to the bug described at the top of this file, each CSR'd custom element
125
+ // must be replaced with the new synthetic constructor. Attributes and children are
126
+ // copied over to the new component.
127
+ const component = initializeWebComponent(elementName, ctor);
128
+ // copy the attributes
129
+ for (const { name, value } of element.attributes) {
130
+ component.setAttribute(name, value);
131
+ const prop = getPropFromAttrName(name);
132
+ if (prop in component) {
133
+ // set attributes as properties for reactivity
134
+ component[prop] = value;
135
+ }
136
+ }
137
+ // save the children
138
+ while (element.childNodes.length > 0) {
139
+ component.appendChild(element.childNodes[0]);
140
+ }
141
+ // swap the element out with the initialized component
142
+ const parent = element.parentElement;
143
+ if (parent) {
144
+ parent.replaceChild(component, element);
145
+ }
146
+ logOperationEnd({
147
+ id: INIT_MODULE,
148
+ specifier,
149
+ specifierIndex,
150
+ metadata: { renderMode: 'csr' },
151
+ });
118
152
  }
119
- // save the children
120
- while (element.childNodes.length > 0) {
121
- component.appendChild(element.childNodes[0]);
122
- }
123
- // swap the element out with the initialized component
124
- const parent = element.parentElement;
125
- if (parent) {
126
- parent.replaceChild(component, element);
127
- }
128
- logOperationEnd({
129
- id: INIT_MODULE,
130
- specifier,
131
- specifierIndex: index,
132
- metadata: { renderMode: 'csr' },
133
- });
134
153
  }
135
- }
154
+ })();
136
155
  logOperationEnd({ id: INIT });
137
156
  logOperationStart({ id: BOOTSTRAP_END });
138
157
  }
158
+ // Allows the browser to yield to the main thread during long-running tasks, improving responsiveness.
159
+ async function yieldToMainThread() {
160
+ const scheduler = globalThis.scheduler;
161
+ // eslint-disable-next-line lwr/no-unguarded-apis
162
+ return scheduler?.yield ? scheduler.yield() : new Promise((resolve) => setTimeout(resolve, 0));
163
+ }
139
164
  //# sourceMappingURL=init.js.map
@@ -10,6 +10,7 @@ export function attachDispatcher(dispatcher) {
10
10
  }
11
11
  // Check if the Performance API is available
12
12
  // e.g. JSDom (used in Jest) doesn't implement these
13
+ // eslint-disable-next-line
13
14
  const perf = globalThis.performance;
14
15
  const isPerfSupported = typeof perf !== 'undefined' &&
15
16
  typeof perf.mark === 'function' &&
@@ -34,7 +35,7 @@ function getDetail(specifier, metadata) {
34
35
  // Fallback to the Performance API if there is no custom dispatcher
35
36
  export function logOperationStart({ id, specifier, specifierIndex, metadata }) {
36
37
  if (customDispatcher) {
37
- customDispatcher({ id, phase: Phase.Start, specifier, metadata });
38
+ customDispatcher({ id, phase: Phase.Start, specifier, metadata, specifierIndex });
38
39
  return;
39
40
  }
40
41
  if (isPerfSupported) {
@@ -48,7 +49,7 @@ export function logOperationStart({ id, specifier, specifierIndex, metadata }) {
48
49
  /* istanbul ignore next */
49
50
  export function logOperationEnd({ id, specifier, specifierIndex, metadata }) {
50
51
  if (customDispatcher) {
51
- customDispatcher({ id, phase: Phase.End, specifier, metadata });
52
+ customDispatcher({ id, phase: Phase.End, specifier, metadata, specifierIndex });
52
53
  }
53
54
  else if (isPerfSupported) {
54
55
  const markName = getMarkName(id, specifier, specifierIndex);
@@ -32,7 +32,10 @@ function updateStaleModule({ oldModule, newModule, specifier }) {
32
32
  swapStyle(oldModule.default[0], newModule.default[0]);
33
33
  } else {
34
34
  console.log(`Swapping JS for module "${specifier}"`);
35
- swapComponent(oldModule.default, newModule.default);
35
+ const success = swapComponent(oldModule.default, newModule.default);
36
+ if (!success) {
37
+ window.location.reload();
38
+ }
36
39
  }
37
40
  }
38
41
 
@@ -1,29 +1,49 @@
1
+ // eslint-disable-next-line lwr/only-allowed-type-imports
2
+
3
+ // eslint-disable-next-line lwr/only-allowed-type-imports
4
+
1
5
  import { BOOTSTRAP_END, INIT, INIT_MODULE } from 'lwr/metrics';
2
6
  import { logOperationStart, logOperationEnd } from 'lwr/profiler';
3
7
 
4
8
  // TODO: This is a temporal workaround until https://github.com/salesforce/lwc/pull/2083 is sorted - tmp
9
+ // eslint-disable-next-line lwr/only-allowed-imports
5
10
  import { createElement } from 'lwc';
6
11
 
7
12
  // <hydrateComponentProxy> - This code is removed in core
8
13
  // Note: a build step uses these comments to strip the code for core.
14
+ // eslint-disable-next-line lwr/only-allowed-imports
9
15
  import { hydrateComponent } from 'lwc';
10
16
  function hydrateComponentProxy(customElement, Ctor, props) {
11
17
  hydrateComponent(customElement, Ctor, props);
12
18
  }
13
19
  // </hydrateComponentProxy>
14
20
 
15
- // Break up hydration tasks into timed batches.
16
- // Borrowed from https://tinyurl.com/5b4fw7eb
17
- const HYDRATION_TASK_BATCH_DURATION = 50;
18
- let timeOfLastYield = performance.now();
19
- function shouldYield() {
20
- const now = performance.now();
21
- if (now - timeOfLastYield > HYDRATION_TASK_BATCH_DURATION) {
22
- timeOfLastYield = now;
23
- return true;
21
+ const shouldYield = (() => {
22
+ const globalThisLWR = globalThis;
23
+ const {
24
+ SSREnabled
25
+ } = globalThisLWR.LWR && globalThisLWR.LWR.env || {};
26
+
27
+ // eslint-disable-next-line lwr/no-unguarded-apis
28
+ if (!globalThis.performance || !SSREnabled) {
29
+ return () => false;
24
30
  }
25
- return false;
26
- }
31
+
32
+ // Break up hydration tasks into timed batches.
33
+ // Borrowed from https://tinyurl.com/5b4fw7eb
34
+ const TASK_BATCH_DURATION = 50;
35
+ // eslint-disable-next-line lwr/no-unguarded-apis
36
+ let timeOfLastYield = globalThis.performance.now();
37
+ return () => {
38
+ // eslint-disable-next-line lwr/no-unguarded-apis
39
+ const now = globalThis.performance.now();
40
+ if (now - timeOfLastYield > TASK_BATCH_DURATION) {
41
+ timeOfLastYield = now;
42
+ return true;
43
+ }
44
+ return false;
45
+ };
46
+ })();
27
47
  function initializeWebComponent(elementName, Ctor) {
28
48
  return createElement(elementName, {
29
49
  is: Ctor
@@ -61,7 +81,8 @@ export function getPropFromAttrName(propName) {
61
81
  * @example - [['x/appRoot', appCtor], ['x/nav', navCtor]]
62
82
  */
63
83
  export function init(rootModules, serverData = {}) {
64
- if (typeof customElements === 'undefined' || typeof document === 'undefined') {
84
+ // eslint-disable-next-line lwr/no-unguarded-apis
85
+ if (typeof globalThis.customElements === 'undefined' || typeof globalThis.document === 'undefined') {
65
86
  logOperationStart({
66
87
  id: BOOTSTRAP_END
67
88
  });
@@ -70,106 +91,120 @@ export function init(rootModules, serverData = {}) {
70
91
  logOperationStart({
71
92
  id: INIT
72
93
  });
73
- let index = 0;
74
- for (const [specifier, ctor] of rootModules) {
75
- const elementName = toKebabCase(specifier);
76
-
77
- // initialize and inject the root module into the LWR Root or DOM if it is missing
78
- if (!document.body.querySelector(elementName)) {
79
- logOperationStart({
80
- id: INIT_MODULE,
81
- specifier,
82
- specifierIndex: ++index
83
- });
84
-
85
- // this is for SPA like routes (one component at the root level) utilizing the lwr-root directive
86
- const component = initializeWebComponent(elementName, ctor);
87
- const container = document.querySelector('[lwr-root]');
88
- container ? container.appendChild(component) : document.body.appendChild(component);
89
- logOperationEnd({
90
- id: INIT_MODULE,
91
- specifier,
92
- specifierIndex: index,
93
- metadata: {
94
- renderMode: 'spa'
95
- }
96
- });
97
- continue;
98
- }
94
+ (async () => {
95
+ let index = 0;
96
+ // eslint-disable-next-line lwr/no-unguarded-apis
97
+ const document = globalThis.document;
98
+ for (const [specifier, ctor] of rootModules) {
99
+ if (shouldYield()) {
100
+ // Yield to the main thread during long hydration tasks
101
+ // eslint-disable-next-line no-await-in-loop
102
+ await yieldToMainThread();
103
+ }
104
+ const specifierIndex = ++index;
105
+ const elementName = toKebabCase(specifier);
99
106
 
100
- // the page has been rendered or SSR'd, and each component needs to initialized(or hydrated)
101
- const elements = document.querySelectorAll(elementName);
102
- for (const element of elements) {
103
- logOperationStart({
104
- id: INIT_MODULE,
105
- specifier,
106
- specifierIndex: ++index
107
- });
108
- const propsId = element.dataset.lwrPropsId;
109
-
110
- // hydrate SSR'd components
111
- if (propsId) {
112
- if (shouldYield()) {
113
- // give room for the browser to render during long hydration tasks
114
- setTimeout(() => {
115
- hydrateComponentProxy(element, ctor, serverData[propsId] || {});
116
- }, 0);
117
- } else {
118
- hydrateComponentProxy(element, ctor, serverData[propsId] || {});
119
- }
107
+ // initialize and inject the root module into the LWR Root or DOM if it is missing
108
+ // eslint-disable-next-line lwr/no-unguarded-apis
109
+ if (!document.body.querySelector(elementName)) {
110
+ logOperationStart({
111
+ id: INIT_MODULE,
112
+ specifier,
113
+ specifierIndex
114
+ });
115
+
116
+ // this is for SPA like routes (one component at the root level) utilizing the lwr-root directive
117
+ const component = initializeWebComponent(elementName, ctor);
118
+ // eslint-disable-next-line lwr/no-unguarded-apis
119
+ const container = document.querySelector('[lwr-root]');
120
+ // eslint-disable-next-line lwr/no-unguarded-apis
121
+ container ? container.appendChild(component) : document.body.appendChild(component);
120
122
  logOperationEnd({
121
123
  id: INIT_MODULE,
122
124
  specifier,
123
- specifierIndex: index,
125
+ specifierIndex,
124
126
  metadata: {
125
- renderMode: 'ssr'
127
+ renderMode: 'spa'
126
128
  }
127
129
  });
128
130
  continue;
129
131
  }
130
132
 
131
- // Note: due to the bug described at the top of this file, each CSR'd custom element
132
- // must be replaced with the new synthetic constructor. Attributes and children are
133
- // copied over to the new component.
134
- const component = initializeWebComponent(elementName, ctor);
135
-
136
- // copy the attributes
137
- for (const {
138
- name,
139
- value
140
- } of element.attributes) {
141
- component.setAttribute(name, value);
142
- const prop = getPropFromAttrName(name);
143
- if (prop in component) {
144
- // set attributes as properties for reactivity
145
- component[prop] = value;
133
+ // the page has been rendered or SSR'd, and each component needs to initialized(or hydrated)
134
+ // eslint-disable-next-line lwr/no-unguarded-apis
135
+ const elements = document.querySelectorAll(elementName);
136
+ for (const element of elements) {
137
+ logOperationStart({
138
+ id: INIT_MODULE,
139
+ specifier,
140
+ specifierIndex
141
+ });
142
+ const propsId = element.dataset.lwrPropsId;
143
+
144
+ // hydrate SSR'd components
145
+ if (propsId) {
146
+ hydrateComponentProxy(element, ctor, serverData[propsId] || {});
147
+ logOperationEnd({
148
+ id: INIT_MODULE,
149
+ specifier,
150
+ specifierIndex,
151
+ metadata: {
152
+ renderMode: 'ssr'
153
+ }
154
+ });
155
+ continue;
146
156
  }
147
- }
148
157
 
149
- // save the children
150
- while (element.childNodes.length > 0) {
151
- component.appendChild(element.childNodes[0]);
152
- }
158
+ // Note: due to the bug described at the top of this file, each CSR'd custom element
159
+ // must be replaced with the new synthetic constructor. Attributes and children are
160
+ // copied over to the new component.
161
+ const component = initializeWebComponent(elementName, ctor);
153
162
 
154
- // swap the element out with the initialized component
155
- const parent = element.parentElement;
156
- if (parent) {
157
- parent.replaceChild(component, element);
158
- }
159
- logOperationEnd({
160
- id: INIT_MODULE,
161
- specifier,
162
- specifierIndex: index,
163
- metadata: {
164
- renderMode: 'csr'
163
+ // copy the attributes
164
+ for (const {
165
+ name,
166
+ value
167
+ } of element.attributes) {
168
+ component.setAttribute(name, value);
169
+ const prop = getPropFromAttrName(name);
170
+ if (prop in component) {
171
+ // set attributes as properties for reactivity
172
+ component[prop] = value;
173
+ }
165
174
  }
166
- });
175
+
176
+ // save the children
177
+ while (element.childNodes.length > 0) {
178
+ component.appendChild(element.childNodes[0]);
179
+ }
180
+
181
+ // swap the element out with the initialized component
182
+ const parent = element.parentElement;
183
+ if (parent) {
184
+ parent.replaceChild(component, element);
185
+ }
186
+ logOperationEnd({
187
+ id: INIT_MODULE,
188
+ specifier,
189
+ specifierIndex,
190
+ metadata: {
191
+ renderMode: 'csr'
192
+ }
193
+ });
194
+ }
167
195
  }
168
- }
196
+ })();
169
197
  logOperationEnd({
170
198
  id: INIT
171
199
  });
172
200
  logOperationStart({
173
201
  id: BOOTSTRAP_END
174
202
  });
203
+ }
204
+
205
+ // Allows the browser to yield to the main thread during long-running tasks, improving responsiveness.
206
+ async function yieldToMainThread() {
207
+ const scheduler = globalThis.scheduler;
208
+ // eslint-disable-next-line lwr/no-unguarded-apis
209
+ return scheduler?.yield ? scheduler.yield() : new Promise(resolve => setTimeout(resolve, 0));
175
210
  }