How to use getLowestPriorityLane method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

ReactFiberLane.js

Source: ReactFiberLane.js Github

copy
1export const SyncLanePriority = 15;
2export const SyncBatchedLanePriority = 14;
3
4const InputDiscreteHydrationLanePriority = 13;
5export const InputDiscreteLanePriority = 12;
6
7const InputContinuousHydrationLanePriority = 11;
8export const InputContinuousLanePriority = 10;
9
10const DefaultHydrationLanePriority = 9;
11export const DefaultLanePriority = 8;
12
13const TransitionHydrationPriority = 7;
14export const TransitionPriority = 6;
15
16const RetryLanePriority = 5;
17
18const SelectiveHydrationLanePriority = 4;
19
20const IdleHydrationLanePriority = 3;
21const IdleLanePriority = 2;
22
23const OffscreenLanePriority = 1;
24
25export const NoLanePriority = 0;
26
27const TotalLanes = 31;
28
29export const NoLanePriority = 0;
30
31export const NoLanes = /*                         */ 0b0000000000000000000000000000000;
32export const NoLane = /*                          */ 0b0000000000000000000000000000000;
33export const SyncLane = /*                        */ 0b0000000000000000000000000000001;
34export const SyncBatchedLane = /*                 */ 0b0000000000000000000000000000010;
35
36export const InputDiscreteHydrationLane = /*      */ 0b0000000000000000000000000000100;
37const InputDiscreteLanes = /*                     */ 0b0000000000000000000000000011000;
38
39const InputContinuousHydrationLane = /*           */ 0b0000000000000000000000000100000;
40const InputContinuousLanes = /*                   */ 0b0000000000000000000000011000000;
41
42export const DefaultHydrationLane = /*            */ 0b0000000000000000000000100000000;
43export const DefaultLanes = /*                    */ 0b0000000000000000000111000000000;
44
45const TransitionHydrationLane = /*                */ 0b0000000000000000001000000000000;
46const TransitionLanes = /*                        */ 0b0000000001111111110000000000000;
47
48const RetryLanes = /*                             */ 0b0000011110000000000000000000000;
49
50export const SomeRetryLane = /*                   */ 0b0000010000000000000000000000000;
51
52export const SelectiveHydrationLane = /*          */ 0b0000100000000000000000000000000;
53
54const NonIdleLanes = /*                           */ 0b0000111111111111111111111111111;
55
56export const IdleHydrationLane = /*               */ 0b0001000000000000000000000000000;
57const IdleLanes = /*                              */ 0b0110000000000000000000000000000;
58
59export const OffscreenLane = /*                   */ 0b1000000000000000000000000000000;
60export const NoTimestamp = -1;
61
62let currentUpdateLanePriority = NoLanePriority;
63// "Registers" used to "return" multiple values
64// Used by getHighestPriorityLanes and getNextLanes:
65let return_highestLanePriority = DefaultLanePriority;
66function getHighestPriorityLanes(lanes) {
67  if ((SyncLane & lanes) !== NoLanes) {
68    return_highestLanePriority = SyncLanePriority;
69    return SyncLane;
70  }
71  if ((SyncBatchedLane & lanes) !== NoLanes) {
72    return_highestLanePriority = SyncBatchedLanePriority;
73    return SyncBatchedLane;
74  }
75  if ((InputDiscreteHydrationLane & lanes) !== NoLanes) {
76    return_highestLanePriority = InputDiscreteHydrationLanePriority;
77    return InputDiscreteHydrationLane;
78  }
79  const inputDiscreteLanes = InputDiscreteLanes & lanes;
80  if (inputDiscreteLanes !== NoLanes) {
81    return_highestLanePriority = InputDiscreteLanePriority;
82    return inputDiscreteLanes;
83  }
84  if ((lanes & InputContinuousHydrationLane) !== NoLanes) {
85    return_highestLanePriority = InputContinuousHydrationLanePriority;
86    return InputContinuousHydrationLane;
87  }
88  const inputContinuousLanes = InputContinuousLanes & lanes;
89  if (inputContinuousLanes !== NoLanes) {
90    return_highestLanePriority = InputContinuousLanePriority;
91    return inputContinuousLanes;
92  }
93  if ((lanes & DefaultHydrationLane) !== NoLanes) {
94    return_highestLanePriority = DefaultHydrationLanePriority;
95    return DefaultHydrationLane;
96  }
97  const defaultLanes = DefaultLanes & lanes;
98  if (defaultLanes !== NoLanes) {
99    return_highestLanePriority = DefaultLanePriority;
100    return defaultLanes;
101  }
102  if ((lanes & TransitionHydrationLane) !== NoLanes) {
103    return_highestLanePriority = TransitionHydrationPriority;
104    return TransitionHydrationLane;
105  }
106  const transitionLanes = TransitionLanes & lanes;
107  if (transitionLanes !== NoLanes) {
108    return_highestLanePriority = TransitionPriority;
109    return transitionLanes;
110  }
111  const retryLanes = RetryLanes & lanes;
112  if (retryLanes !== NoLanes) {
113    return_highestLanePriority = RetryLanePriority;
114    return retryLanes;
115  }
116  if (lanes & SelectiveHydrationLane) {
117    return_highestLanePriority = SelectiveHydrationLanePriority;
118    return SelectiveHydrationLane;
119  }
120  if ((lanes & IdleHydrationLane) !== NoLanes) {
121    return_highestLanePriority = IdleHydrationLanePriority;
122    return IdleHydrationLane;
123  }
124  const idleLanes = IdleLanes & lanes;
125  if (idleLanes !== NoLanes) {
126    return_highestLanePriority = IdleLanePriority;
127    return idleLanes;
128  }
129  if ((OffscreenLane & lanes) !== NoLanes) {
130    return_highestLanePriority = OffscreenLanePriority;
131    return OffscreenLane;
132  }
133  // This shouldn't be reachable, but as a fallback, return the entire bitmask.
134  return_highestLanePriority = DefaultLanePriority;
135  return lanes;
136}
137
138// 本质上, 这个函数就是将lanes上, 所以值为1的位中, 除了最高位, 其他都设为0
139// 0b0000000001111111110000000000000 => 0b0000000001000000000000000000000
140// 0b0000000000000000000111000000000 => 0b0000000000000000000100000000000
141// ...
142function getLowestPriorityLane(lanes) {
143  // This finds the most significant non-zero bit.
144  const index = 31 - Math.clz32(lanes);
145
146  //
147  return index < 0 ? NoLanes : 1 << index;
148}
149
150/**
151 * (中文输入法会导致后面的二进制对不齐...)
152 * 1. if lanes = SyncBatchedLane & SyncLanes, said                   0b0000000000000000000000000000011
153 *  result of getLowestPriorityLane(lanes) is SyncBatchedLane, said  0b0000000000000000000000000000010
154 *  << 1                                                             0b0000000000000000000000000000100
155 *  - 1                                                              0b0000000000000000000000000000011
156 *
157 * 2. if lanes = SyncLanes, said                                     0b0000000000000000000000000000001
158 *  result of getLowestPriorityLane(SyncLanes) is SyncLanes, said    0b0000000000000000000000000000001
159 *  << 1                                                             0b0000000000000000000000000000010
160 *  - 1                                                              0b0000000000000000000000000000001
161 *
162 * 3. if lanes = TransitionLanes, said
163 * 0b0000000001111111110000000000000
164 * 0b0000000001000000000000000000000
165 * 0b0000000010000000000000000000000
166 * 0b0000000001111111111111111111111
167 *
168 *
169 * 所以这个函数本质上是先找到lanes中值为1的最高位, 这位设置为0, 其后所有位都设为1
170 */
171function getEqualOrHigherPriorityLanes(lanes) {
172  return (getLowestPriorityLane(lanes) << 1) - 1;
173}
174
175export function createLaneMap(initial) {
176  return new Array(TotalLanes).fill(initial);
177}
178
179export function mergeLanes(a, b) {
180  return a | b;
181}
182function pickArbitraryLaneIndex(lanes) {
183  return 31 - Math.clz32(lanes);
184}
185
186function laneToIndex(lane) {
187  return pickArbitraryLaneIndex(lane);
188}
189export function includesSomeLane(a, b) {
190  return (a & b) !== NoLanes;
191}
192
193export function markRootUpdated(root, updateLane, eventTime) {
194  // 当前更新的lane, 与fiber root node.pendingLanes字段merge
195  root.pendingLanes |= updateLane;
196
197  // TODO: Theoretically, any update to any lane can unblock any other lane. But
198  // it's not practical to try every single possible combination. We need a
199  // heuristic to decide which lanes to attempt to render, and in which batches.
200  // For now, we use the same heuristic as in the old ExpirationTimes model:
201  // retry any lane at equal or lower priority, but don't try updates at higher
202  // priority without also including the lower priority updates. This works well
203  // when considering updates across different priority levels, but isn't
204  // sufficient for updates within the same priority, since we want to treat
205  // those updates as parallel.
206
207  // Unsuspend any update at equal or lower priority.
208  // 对于
209  //   任何 [suspend] 的, [优先级比当前updateLane低或持平]的update
210  // 这里会取消他们的暂停状态?
211  const higherPriorityLanes = updateLane - 1; // Turns 0b1000 into 0b0111
212
213  // 这里还是不懂, 关于lane的按位与, 按位或的逻辑运算
214  // 太抽象了...
215  root.suspendedLanes &= higherPriorityLanes;
216  root.pingedLanes &= higherPriorityLanes;
217
218  const eventTimes = root.eventTimes;
219  const index = laneToIndex(updateLane);
220  // We can always overwrite an existing timestamp because we prefer the most
221  // recent event, and we assume time is monotonically increasing(单调递增).
222  eventTimes[index] = eventTime;
223}
224
225export function getNextLanes(root, wipLanes) {
226  // 首次渲染时, 在本文件27行, 设置了root上的pendingLanes为1
227  const pendingLanes = root.pendingLanes;
228  // Early bailout if there's no pending work left.
229  if (pendingLanes === NoLanes) {
230    return_highestLanePriority = NoLanePriority;
231    return NoLanes;
232  }
233
234  let nextLanes = NoLanes;
235  let nextLanePriority = NoLanePriority;
236
237  // 初次渲染时, 以下几个lanes均为0
238  const expiredLanes = root.expiredLanes;
239  const suspendedLanes = root.suspendedLanes;
240  const pingedLanes = root.pingedLanes;
241
242  // Check if any work has expired.
243  // 如果有过期的lane, 下一个lane即为这个过期的lane, 下一个lane优先级就是同步lane优先级 = 15
244  // 初次渲染时不应该有过期lanes
245  if (expiredLanes !== NoLanes) {
246    nextLanes = expiredLanes;
247    nextLanePriority = return_highestLanePriority = SyncLanePriority;
248  } else {
249    // Do not work on any idle work until all the non-idle work has finished,
250    // even if the work is suspended.
251    // 按位与运算取出所有正在进行中的, 且不在idle lanes上的lanes
252    const nonIdlePendingLanes = pendingLanes & NonIdleLanes;
253    if (nonIdlePendingLanes !== NoLanes) {
254      // 如果存在工作
255      // 跟按位取反的suspendedLanes按位与运算, 也就是从非idle任务中再过滤掉所有挂起的lanes
256      const nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;
257      if (nonIdleUnblockedLanes !== NoLanes) {
258        // 正如变量名所示的, 现在的lanes是所有的非idle, 非blocked的lanes了
259        // getHighestPriorityLanes使用一系列if, 找到在这些lanes中, 优先级最高的lanes
260        // SyncLane > SyncBatchedLane > InputDiscreteHydrationLane > inputDiscreteLanes > ... > idleLanes >  OffscreenLane
261
262        // 初次渲染应该是这条分路
263        nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);
264        nextLanePriority = return_highestLanePriority;
265      } else {
266        // 若所有的非idle lanes都是suspendedLanes
267        const nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;
268        if (nonIdlePingedLanes !== NoLanes) {
269          // 再看这些lanes里面有没有pingedLanes
270          // 如果有, 从这些lanes中找到最高优先级的lanes
271          nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
272          nextLanePriority = return_highestLanePriority;
273        }
274      }
275    } else {
276      // The only remaining work is Idle.
277      // 如果只存在idle lanes
278      // 和上面一样, 从这些lanes里面先选择所有的非suspended Lanes中优先级最高的,
279      const unblockedLanes = pendingLanes & ~suspendedLanes;
280      if (unblockedLanes !== NoLanes) {
281        nextLanes = getHighestPriorityLanes(unblockedLanes);
282        nextLanePriority = return_highestLanePriority;
283      } else {
284        // 这里有个小细节, 不再用pending lanes和pinged lanes做按位与了
285        // 其实到了这个分支, 我们已经可以判定, 剩下的lanes 都是 pinged lanes, 所以无需再做一次位运算了
286        if (pingedLanes !== NoLanes) {
287          nextLanes = getHighestPriorityLanes(pingedLanes);
288          nextLanePriority = return_highestLanePriority;
289        }
290      }
291    }
292  }
293
294  // 只有在被挂起时才会出现这种状态
295  if (nextLanes === NoLanes) {
296    // This should only be reachable if we're suspended
297    // TODO: Consider warning in this path if a fallback timer is not scheduled.
298    return NoLanes;
299  }
300
301  // If there are higher priority lanes, we'll include them even if they
302  // are suspended.
303  // getEqualOrHigherPriorityLanes 先在nextLanes上找到优先级最低的lane, 然后左移1位再减1
304  // 首次渲染时此处没有影响, 结果依然时 nextLanes = SyncLane
305  // 换句话说, 没有比SyncLane优先级更高的lane了
306  nextLanes = pendingLanes & getEqualOrHigherPriorityLanes(nextLanes);
307
308  // If we're already in the middle of a render, switching lanes will interrupt
309  // it and we'll lose our progress. We should only do this if the new lanes are
310  // higher priority.
311  // 初次渲染时, wipLanes应该是0, 因为此时还没有任何“work in progress”工作呀
312  // 若不在初次渲染, 且wipLanes不是NoLanes, 这说明现在正在render阶段, 如果此时重新选择lanes会导致
313  // 这个在进行的render工作被打断, 所以我们仅当新的工作优先级高于正在进行的工作时才重新选择lanes
314  // 否则返回正在进行中的lanes
315  if (
316    wipLanes !== NoLanes &&
317    wipLanes !== nextLanes &&
318    // If we already suspended with a delay, then interrupting is fine. Don't
319    // bother waiting until the root is complete.
320    (wipLanes & suspendedLanes) === NoLanes
321  ) {
322    getHighestPriorityLanes(wipLanes);
323    const wipLanePriority = return_highestLanePriority;
324    // 在这里判断新工作的优先级是否高于正在进行中的工作的优先级
325    if (nextLanePriority <= wipLanePriority) {
326      return wipLanes;
327    } else {
328      return_highestLanePriority = nextLanePriority;
329    }
330  }
331
332  // Check for entangled lanes and add them to the batch.
333  //
334  // A lane is said to be entangled with another when it's not allowed to render
335  // in a batch that does not also include the other lane. Typically we do this
336  // when multiple updates have the same source, and we only want to respond to
337  // the most recent event from that source.
338  //
339  // Note that we apply entanglements *after* checking for partial work above.
340  // This means that if a lane is entangled during an interleaved event while
341  // it's already rendering, we won't interrupt it. This is intentional, since
342  // entanglement is usually "best effort": we'll try our best to render the
343  // lanes in the same batch, but it's not worth throwing out partially
344  // completed work in order to do it.
345  //
346  // For those exceptions where entanglement is semantically important, like
347  // useMutableSource, we should ensure that there is no partial work at the
348  // time we apply the entanglement.
349  // 这段暂时不懂, 跳过
350  // 首次渲染时, entangledLanes为0
351  const entangledLanes = root.entangledLanes;
352  if (entangledLanes !== NoLanes) {
353    const entanglements = root.entanglements;
354    let lanes = nextLanes & entangledLanes;
355    while (lanes > 0) {
356      const index = pickArbitraryLaneIndex(lanes);
357      const lane = 1 << index;
358
359      nextLanes |= entanglements[index];
360
361      lanes &= ~lane;
362    }
363  }
364
365  return nextLanes;
366}
367
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)