@lwrjs/client-modules 0.20.4 → 0.20.6
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.
- package/build/bundle/prod/lwr/init/init.js +1 -1
- package/build/bundle/prod/lwr/lockerDefine/lockerDefine.js +1 -1
- package/build/es/modules/lwr/init/init.js +5 -39
- package/build/es/modules/lwr/scheduler/scheduler.d.ts +21 -0
- package/build/es/modules/lwr/scheduler/scheduler.js +66 -0
- package/build/modules/lwr/init/init.js +5 -47
- package/build/modules/lwr/lockerDefine/lockerDefine.js +361 -427
- package/build/modules/lwr/lockerSandbox/lockerSandbox.js +361 -427
- package/build/modules/lwr/scheduler/scheduler.js +85 -0
- package/package.json +8 -9
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { BOOTSTRAP_END, INIT, INIT_MODULE } from 'lwr/metrics';
|
|
2
2
|
import { logOperationStart, logOperationEnd } from 'lwr/profiler';
|
|
3
|
+
import { yieldIfNecessary } from 'lwr/scheduler';
|
|
3
4
|
// TODO: This is a temporal workaround until https://github.com/salesforce/lwc/pull/2083 is sorted - tmp
|
|
4
5
|
// eslint-disable-next-line lwr/only-allowed-imports
|
|
5
|
-
import { createElement } from 'lwc';
|
|
6
|
-
// <hydrateComponentProxy> - This code is removed in core
|
|
7
|
-
// Note: a build step uses these comments to strip the code for core.
|
|
8
|
-
// eslint-disable-next-line lwr/only-allowed-imports
|
|
9
|
-
import { hydrateComponent } from 'lwc';
|
|
6
|
+
import { createElement, hydrateComponent } from 'lwc';
|
|
10
7
|
// hydration directive + value constants
|
|
11
8
|
// must align with the constants in @lwrjs/shared-utils/src/html-meta.ts
|
|
12
9
|
export const HYDRATE_DIRECTIVE = 'lwr:hydrate';
|
|
@@ -14,7 +11,6 @@ export const HYDRATE_VISIBLE_VALUE = 'visible';
|
|
|
14
11
|
function hydrateComponentProxy(customElement, Ctor, props) {
|
|
15
12
|
hydrateComponent(customElement, Ctor, props);
|
|
16
13
|
}
|
|
17
|
-
// </hydrateComponentProxy>
|
|
18
14
|
/**
|
|
19
15
|
* Hydrate the custom element only when it is visible.
|
|
20
16
|
* @param customElement - The custom element to hydrate
|
|
@@ -77,28 +73,6 @@ function createVisibilityObserver() {
|
|
|
77
73
|
});
|
|
78
74
|
return visibilityObserver;
|
|
79
75
|
}
|
|
80
|
-
const shouldYield = (() => {
|
|
81
|
-
const globalThisLWR = globalThis;
|
|
82
|
-
const { SSREnabled } = (globalThisLWR.LWR && globalThisLWR.LWR.env) || {};
|
|
83
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
84
|
-
if (!globalThis.performance || !SSREnabled) {
|
|
85
|
-
return () => false;
|
|
86
|
-
}
|
|
87
|
-
// Break up hydration tasks into timed batches.
|
|
88
|
-
// Borrowed from https://tinyurl.com/5b4fw7eb
|
|
89
|
-
const TASK_BATCH_DURATION = 50;
|
|
90
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
91
|
-
let timeOfLastYield = globalThis.performance.now();
|
|
92
|
-
return () => {
|
|
93
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
94
|
-
const now = globalThis.performance.now();
|
|
95
|
-
if (now - timeOfLastYield > TASK_BATCH_DURATION) {
|
|
96
|
-
timeOfLastYield = now;
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
return false;
|
|
100
|
-
};
|
|
101
|
-
})();
|
|
102
76
|
function initializeWebComponent(elementName, Ctor) {
|
|
103
77
|
return createElement(elementName, { is: Ctor });
|
|
104
78
|
}
|
|
@@ -145,11 +119,9 @@ export function init(rootModules, serverData = {}) {
|
|
|
145
119
|
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
146
120
|
const document = globalThis.document;
|
|
147
121
|
for (const [specifier, ctor] of rootModules) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
await yieldToMainThread();
|
|
152
|
-
}
|
|
122
|
+
// Yield to the main thread during long hydration tasks
|
|
123
|
+
// eslint-disable-next-line no-await-in-loop
|
|
124
|
+
await yieldIfNecessary();
|
|
153
125
|
const specifierIndex = ++index;
|
|
154
126
|
const elementName = toKebabCase(specifier);
|
|
155
127
|
// initialize and inject the root module into the LWR Root or DOM if it is missing
|
|
@@ -229,10 +201,4 @@ export function init(rootModules, serverData = {}) {
|
|
|
229
201
|
logOperationEnd({ id: INIT });
|
|
230
202
|
logOperationStart({ id: BOOTSTRAP_END });
|
|
231
203
|
}
|
|
232
|
-
// Allows the browser to yield to the main thread during long-running tasks, improving responsiveness.
|
|
233
|
-
async function yieldToMainThread() {
|
|
234
|
-
const scheduler = globalThis.scheduler;
|
|
235
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
236
|
-
return scheduler?.yield ? scheduler.yield() : new Promise((resolve) => setTimeout(resolve, 0));
|
|
237
|
-
}
|
|
238
204
|
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of checking whether to yield to the main thread
|
|
3
|
+
*/
|
|
4
|
+
export interface ShouldYieldResult {
|
|
5
|
+
shouldYield: boolean;
|
|
6
|
+
timeOfLastYield: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Reset the internal yield tracking state. Used primarily for testing.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare function resetYieldTracking(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Yields control to the main thread if enough time has elapsed since the last yield.
|
|
15
|
+
* This automatically tracks yield timing internally to break up long-running tasks
|
|
16
|
+
* into batches, improving responsiveness without requiring manual state management.
|
|
17
|
+
*
|
|
18
|
+
* @returns Promise that resolves after yielding (if necessary) to the main thread
|
|
19
|
+
*/
|
|
20
|
+
export declare function yieldIfNecessary(): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Track the time of last yield for scheduler batching
|
|
2
|
+
let timeOfLastYield = 0;
|
|
3
|
+
/**
|
|
4
|
+
* Reset the internal yield tracking state. Used primarily for testing.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export function resetYieldTracking() {
|
|
8
|
+
timeOfLastYield = 0;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Yields control to the main thread if enough time has elapsed since the last yield.
|
|
12
|
+
* This automatically tracks yield timing internally to break up long-running tasks
|
|
13
|
+
* into batches, improving responsiveness without requiring manual state management.
|
|
14
|
+
*
|
|
15
|
+
* @returns Promise that resolves after yielding (if necessary) to the main thread
|
|
16
|
+
*/
|
|
17
|
+
export async function yieldIfNecessary() {
|
|
18
|
+
const result = checkShouldYield(timeOfLastYield);
|
|
19
|
+
if (result.shouldYield) {
|
|
20
|
+
timeOfLastYield = result.timeOfLastYield;
|
|
21
|
+
await yieldToMainThread();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Checks if the current execution should yield to the main thread based on elapsed time.
|
|
26
|
+
* Break up long-running tasks into timed batches to improve responsiveness.
|
|
27
|
+
* Borrowed from https://tinyurl.com/5b4fw7eb
|
|
28
|
+
*
|
|
29
|
+
* @param timeOfLastYield - Timestamp of the last yield (from performance.now())
|
|
30
|
+
* @returns Object containing whether to yield and the updated timestamp
|
|
31
|
+
*/
|
|
32
|
+
function checkShouldYield(timeOfLastYield) {
|
|
33
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
34
|
+
if (!globalThis.performance || !getSSREnabled()) {
|
|
35
|
+
return { shouldYield: false, timeOfLastYield };
|
|
36
|
+
}
|
|
37
|
+
const TASK_BATCH_DURATION = 50;
|
|
38
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
39
|
+
const now = globalThis.performance.now();
|
|
40
|
+
if (now - timeOfLastYield > TASK_BATCH_DURATION) {
|
|
41
|
+
return { shouldYield: true, timeOfLastYield: now };
|
|
42
|
+
}
|
|
43
|
+
return { shouldYield: false, timeOfLastYield };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Yields control to the main thread during long-running tasks to improve responsiveness.
|
|
47
|
+
* Uses the scheduler.yield() API if available, otherwise falls back to setTimeout.
|
|
48
|
+
*
|
|
49
|
+
* @returns Promise that resolves after yielding to the main thread
|
|
50
|
+
*/
|
|
51
|
+
async function yieldToMainThread() {
|
|
52
|
+
const scheduler = globalThis.scheduler;
|
|
53
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
54
|
+
return scheduler?.yield ? scheduler.yield() : new Promise((resolve) => setTimeout(resolve, 0));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Gets the SSREnabled flag from the global LWR environment
|
|
58
|
+
*
|
|
59
|
+
* @returns Whether SSR is enabled
|
|
60
|
+
*/
|
|
61
|
+
function getSSREnabled() {
|
|
62
|
+
const globalThisLWR = globalThis;
|
|
63
|
+
const { SSREnabled } = (globalThisLWR.LWR && globalThisLWR.LWR.env) || {};
|
|
64
|
+
return !!SSREnabled;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
// eslint-disable-next-line lwr/only-allowed-type-imports
|
|
2
2
|
|
|
3
|
-
// eslint-disable-next-line lwr/only-allowed-type-imports
|
|
4
|
-
|
|
5
3
|
import { BOOTSTRAP_END, INIT, INIT_MODULE } from 'lwr/metrics';
|
|
6
4
|
import { logOperationStart, logOperationEnd } from 'lwr/profiler';
|
|
5
|
+
import { yieldIfNecessary } from 'lwr/scheduler';
|
|
7
6
|
|
|
8
7
|
// TODO: This is a temporal workaround until https://github.com/salesforce/lwc/pull/2083 is sorted - tmp
|
|
9
8
|
// eslint-disable-next-line lwr/only-allowed-imports
|
|
10
|
-
import { createElement } from 'lwc';
|
|
11
|
-
|
|
12
|
-
// <hydrateComponentProxy> - This code is removed in core
|
|
13
|
-
// Note: a build step uses these comments to strip the code for core.
|
|
14
|
-
// eslint-disable-next-line lwr/only-allowed-imports
|
|
15
|
-
import { hydrateComponent } from 'lwc';
|
|
9
|
+
import { createElement, hydrateComponent } from 'lwc';
|
|
16
10
|
|
|
17
11
|
// hydration directive + value constants
|
|
18
12
|
// must align with the constants in @lwrjs/shared-utils/src/html-meta.ts
|
|
@@ -21,7 +15,6 @@ export const HYDRATE_VISIBLE_VALUE = 'visible';
|
|
|
21
15
|
function hydrateComponentProxy(customElement, Ctor, props) {
|
|
22
16
|
hydrateComponent(customElement, Ctor, props);
|
|
23
17
|
}
|
|
24
|
-
// </hydrateComponentProxy>
|
|
25
18
|
|
|
26
19
|
/**
|
|
27
20
|
* Hydrate the custom element only when it is visible.
|
|
@@ -97,32 +90,6 @@ function createVisibilityObserver() {
|
|
|
97
90
|
});
|
|
98
91
|
return visibilityObserver;
|
|
99
92
|
}
|
|
100
|
-
const shouldYield = (() => {
|
|
101
|
-
const globalThisLWR = globalThis;
|
|
102
|
-
const {
|
|
103
|
-
SSREnabled
|
|
104
|
-
} = globalThisLWR.LWR && globalThisLWR.LWR.env || {};
|
|
105
|
-
|
|
106
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
107
|
-
if (!globalThis.performance || !SSREnabled) {
|
|
108
|
-
return () => false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Break up hydration tasks into timed batches.
|
|
112
|
-
// Borrowed from https://tinyurl.com/5b4fw7eb
|
|
113
|
-
const TASK_BATCH_DURATION = 50;
|
|
114
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
115
|
-
let timeOfLastYield = globalThis.performance.now();
|
|
116
|
-
return () => {
|
|
117
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
118
|
-
const now = globalThis.performance.now();
|
|
119
|
-
if (now - timeOfLastYield > TASK_BATCH_DURATION) {
|
|
120
|
-
timeOfLastYield = now;
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
};
|
|
125
|
-
})();
|
|
126
93
|
function initializeWebComponent(elementName, Ctor) {
|
|
127
94
|
return createElement(elementName, {
|
|
128
95
|
is: Ctor
|
|
@@ -175,11 +142,9 @@ export function init(rootModules, serverData = {}) {
|
|
|
175
142
|
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
176
143
|
const document = globalThis.document;
|
|
177
144
|
for (const [specifier, ctor] of rootModules) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
await yieldToMainThread();
|
|
182
|
-
}
|
|
145
|
+
// Yield to the main thread during long hydration tasks
|
|
146
|
+
// eslint-disable-next-line no-await-in-loop
|
|
147
|
+
await yieldIfNecessary();
|
|
183
148
|
const specifierIndex = ++index;
|
|
184
149
|
const elementName = toKebabCase(specifier);
|
|
185
150
|
|
|
@@ -286,11 +251,4 @@ export function init(rootModules, serverData = {}) {
|
|
|
286
251
|
logOperationStart({
|
|
287
252
|
id: BOOTSTRAP_END
|
|
288
253
|
});
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Allows the browser to yield to the main thread during long-running tasks, improving responsiveness.
|
|
292
|
-
async function yieldToMainThread() {
|
|
293
|
-
const scheduler = globalThis.scheduler;
|
|
294
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
295
|
-
return scheduler?.yield ? scheduler.yield() : new Promise(resolve => setTimeout(resolve, 0));
|
|
296
254
|
}
|