@lwc/engine-core 8.0.0 → 8.1.0-alpha.1
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/dist/advanced-mutation-tracker.d.ts +7 -0
- package/dist/framework/advanced-instrumentation.d.ts +2 -0
- package/dist/framework/advanced-mutation-tracker.d.ts +7 -0
- package/dist/framework/mutation-logger.d.ts +34 -0
- package/dist/framework/profiler.d.ts +5 -2
- package/dist/framework/profiling/advanced-instrumentation.d.ts +2 -0
- package/dist/framework/profiling/advanced-mutation-tracker.d.ts +7 -0
- package/dist/index.cjs.js +362 -122
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +363 -123
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Copyright (c) 2024 Salesforce, Inc.
|
|
3
3
|
*/
|
|
4
|
-
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty,
|
|
4
|
+
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, seal, create, isAPIFeatureEnabled, isArray as isArray$1, isFunction as isFunction$1, keys, ArrayFilter, isObject, toString as toString$1, ArrayIndexOf, ArrayPop, isFalse, hasOwnProperty as hasOwnProperty$1, entries, AriaPropNameToAttrNameMap, getPropertyDescriptor, forEach, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, assert, freeze, KEY__SYNTHETIC_MODE, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, ArraySplice, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, isNumber, StringReplace, StringTrim, ArraySort, ArrayFrom, htmlEscape, StringCharAt, ArrayUnshift, LOWEST_API_VERSION, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, StringSplit, arrayEvery, ArrayIncludes, ArrayCopyWithin, ArrayFill, ArrayReverse, ArrayShift } from '@lwc/shared';
|
|
5
5
|
export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
|
|
6
6
|
|
|
7
7
|
/*
|
|
@@ -176,7 +176,208 @@ function logWarnOnce(message, vm) {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/*
|
|
179
|
-
* Copyright (c)
|
|
179
|
+
* Copyright (c) 2018, salesforce.com, inc.
|
|
180
|
+
* All rights reserved.
|
|
181
|
+
* SPDX-License-Identifier: MIT
|
|
182
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
183
|
+
*/
|
|
184
|
+
let nextTickCallbackQueue = [];
|
|
185
|
+
const SPACE_CHAR = 32;
|
|
186
|
+
const EmptyObject = seal(create(null));
|
|
187
|
+
const EmptyArray = seal([]);
|
|
188
|
+
function flushCallbackQueue() {
|
|
189
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
190
|
+
if (nextTickCallbackQueue.length === 0) {
|
|
191
|
+
throw new Error(`Internal Error: If callbackQueue is scheduled, it is because there must be at least one callback on this pending queue.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const callbacks = nextTickCallbackQueue;
|
|
195
|
+
nextTickCallbackQueue = []; // reset to a new queue
|
|
196
|
+
for (let i = 0, len = callbacks.length; i < len; i += 1) {
|
|
197
|
+
callbacks[i]();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function addCallbackToNextTick(callback) {
|
|
201
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
202
|
+
if (!isFunction$1(callback)) {
|
|
203
|
+
throw new Error(`Internal Error: addCallbackToNextTick() can only accept a function callback`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (nextTickCallbackQueue.length === 0) {
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
208
|
+
Promise.resolve().then(flushCallbackQueue);
|
|
209
|
+
}
|
|
210
|
+
ArrayPush$1.call(nextTickCallbackQueue, callback);
|
|
211
|
+
}
|
|
212
|
+
function guid() {
|
|
213
|
+
function s4() {
|
|
214
|
+
return Math.floor((1 + Math.random()) * 0x10000)
|
|
215
|
+
.toString(16)
|
|
216
|
+
.substring(1);
|
|
217
|
+
}
|
|
218
|
+
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
|
219
|
+
}
|
|
220
|
+
// Borrowed from Vue template compiler.
|
|
221
|
+
// https://github.com/vuejs/vue/blob/531371b818b0e31a989a06df43789728f23dc4e8/src/platforms/web/util/style.js#L5-L16
|
|
222
|
+
const DECLARATION_DELIMITER = /;(?![^(]*\))/g;
|
|
223
|
+
const PROPERTY_DELIMITER = /:(.+)/;
|
|
224
|
+
function parseStyleText(cssText) {
|
|
225
|
+
const styleMap = {};
|
|
226
|
+
const declarations = cssText.split(DECLARATION_DELIMITER);
|
|
227
|
+
for (const declaration of declarations) {
|
|
228
|
+
if (declaration) {
|
|
229
|
+
const [prop, value] = declaration.split(PROPERTY_DELIMITER);
|
|
230
|
+
if (prop !== undefined && value !== undefined) {
|
|
231
|
+
styleMap[prop.trim()] = value.trim();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return styleMap;
|
|
236
|
+
}
|
|
237
|
+
// Make a shallow copy of an object but omit the given key
|
|
238
|
+
function cloneAndOmitKey(object, keyToOmit) {
|
|
239
|
+
const result = {};
|
|
240
|
+
for (const key of keys(object)) {
|
|
241
|
+
if (key !== keyToOmit) {
|
|
242
|
+
result[key] = object[key];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
function flattenStylesheets(stylesheets) {
|
|
248
|
+
const list = [];
|
|
249
|
+
for (const stylesheet of stylesheets) {
|
|
250
|
+
if (!isArray$1(stylesheet)) {
|
|
251
|
+
list.push(stylesheet);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
list.push(...flattenStylesheets(stylesheet));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return list;
|
|
258
|
+
}
|
|
259
|
+
// Throw an error if we're running in prod mode. Ensures code is truly removed from prod mode.
|
|
260
|
+
function assertNotProd() {
|
|
261
|
+
/* istanbul ignore if */
|
|
262
|
+
if (process.env.NODE_ENV === 'production') {
|
|
263
|
+
// this method should never leak to prod
|
|
264
|
+
throw new ReferenceError();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function shouldBeFormAssociated(Ctor) {
|
|
268
|
+
const ctorFormAssociated = Boolean(Ctor.formAssociated);
|
|
269
|
+
const apiVersion = getComponentAPIVersion(Ctor);
|
|
270
|
+
const apiFeatureEnabled = isAPIFeatureEnabled(7 /* APIFeature.ENABLE_ELEMENT_INTERNALS_AND_FACE */, apiVersion);
|
|
271
|
+
if (process.env.NODE_ENV !== 'production' && ctorFormAssociated && !apiFeatureEnabled) {
|
|
272
|
+
const tagName = getComponentRegisteredName(Ctor);
|
|
273
|
+
logWarnOnce(`Component <${tagName}> set static formAssociated to true, but form ` +
|
|
274
|
+
`association is not enabled because the API version is ${apiVersion}. To enable form association, ` +
|
|
275
|
+
`update the LWC component API version to 61 or above. https://lwc.dev/guide/versioning`);
|
|
276
|
+
}
|
|
277
|
+
return ctorFormAssociated && apiFeatureEnabled;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/*
|
|
281
|
+
* Copyright (c) 2024, Salesforce, Inc.
|
|
282
|
+
* All rights reserved.
|
|
283
|
+
* SPDX-License-Identifier: MIT
|
|
284
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
285
|
+
*/
|
|
286
|
+
//
|
|
287
|
+
// Do additional mutation tracking for DevTools performance profiling, in dev mode only.
|
|
288
|
+
//
|
|
289
|
+
const reactiveObserversToVMs = new WeakMap();
|
|
290
|
+
const targetsToPropertyKeys = new WeakMap();
|
|
291
|
+
let mutationLogs = [];
|
|
292
|
+
/**
|
|
293
|
+
* Flush all the logs we've written so far and return the current logs.
|
|
294
|
+
*/
|
|
295
|
+
function getAndFlushMutationLogs() {
|
|
296
|
+
assertNotProd();
|
|
297
|
+
const result = mutationLogs;
|
|
298
|
+
mutationLogs = [];
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Log a new mutation for this reactive observer.
|
|
303
|
+
* @param reactiveObserver - relevant ReactiveObserver
|
|
304
|
+
* @param target - target object that is being observed
|
|
305
|
+
* @param key - key (property) that was mutated
|
|
306
|
+
*/
|
|
307
|
+
function logMutation(reactiveObserver, target, key) {
|
|
308
|
+
assertNotProd();
|
|
309
|
+
const parentKey = targetsToPropertyKeys.get(target);
|
|
310
|
+
const vm = reactiveObserversToVMs.get(reactiveObserver);
|
|
311
|
+
/* istanbul ignore if */
|
|
312
|
+
if (isUndefined$1(vm)) {
|
|
313
|
+
// VM should only be undefined in Vitest tests, where a reactive observer is not always associated with a VM
|
|
314
|
+
// because the unit tests just create Reactive Observers on-the-fly.
|
|
315
|
+
// Note we could explicitly target Vitest with `process.env.NODE_ENV === 'test'`, but then that would also
|
|
316
|
+
// affect our downstream consumers' Jest/Vitest tests, and we don't want to throw an error just for a logger.
|
|
317
|
+
if (process.env.NODE_ENV === 'test-karma-lwc') {
|
|
318
|
+
throw new Error('The VM should always be defined except possibly in unit tests');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
const stringKey = toString$1(key);
|
|
323
|
+
let prop;
|
|
324
|
+
if (isUndefined$1(parentKey)) {
|
|
325
|
+
prop = stringKey;
|
|
326
|
+
}
|
|
327
|
+
else if (/^\w+$/.test(stringKey)) {
|
|
328
|
+
// Human-readable prop like `items[0].name` on a deep object/array
|
|
329
|
+
prop = `${toString$1(parentKey)}.${stringKey}`;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
// e.g. `obj["prop with spaces"]`
|
|
333
|
+
prop = `${toString$1(parentKey)}[${JSON.stringify(stringKey)}]`;
|
|
334
|
+
}
|
|
335
|
+
ArrayPush$1.call(mutationLogs, { vm, prop });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Flush logs associated with a given VM.
|
|
340
|
+
* @param vm - given VM
|
|
341
|
+
*/
|
|
342
|
+
function flushMutationLogsForVM(vm) {
|
|
343
|
+
assertNotProd();
|
|
344
|
+
mutationLogs = ArrayFilter.call(mutationLogs, (log) => log.vm !== vm);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Mark this ReactiveObserver as related to this VM. This is only needed for mutation tracking in dev mode.
|
|
348
|
+
* @param reactiveObserver
|
|
349
|
+
* @param vm
|
|
350
|
+
*/
|
|
351
|
+
function associateReactiveObserverWithVM(reactiveObserver, vm) {
|
|
352
|
+
assertNotProd();
|
|
353
|
+
reactiveObserversToVMs.set(reactiveObserver, vm);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Deeply track all objects in a target and associate with a given key.
|
|
357
|
+
* @param key - key associated with the object in the component
|
|
358
|
+
* @param target - tracked target object
|
|
359
|
+
*/
|
|
360
|
+
function trackTargetForMutationLogging(key, target) {
|
|
361
|
+
assertNotProd();
|
|
362
|
+
if (isObject(target) && !isNull(target)) {
|
|
363
|
+
// only track non-primitives; others are invalid as WeakMap keys
|
|
364
|
+
targetsToPropertyKeys.set(target, key);
|
|
365
|
+
// Deeply traverse arrays and objects to track every object within
|
|
366
|
+
if (isArray$1(target)) {
|
|
367
|
+
for (let i = 0; i < target.length; i++) {
|
|
368
|
+
trackTargetForMutationLogging(`${toString$1(key)}[${i}]`, target[i]);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
for (const prop of keys(target)) {
|
|
373
|
+
trackTargetForMutationLogging(`${toString$1(key)}.${prop}`, target[prop]);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/*
|
|
380
|
+
* Copyright (c) 2024, Salesforce, Inc.
|
|
180
381
|
* All rights reserved.
|
|
181
382
|
* SPDX-License-Identifier: MIT
|
|
182
383
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
@@ -199,6 +400,9 @@ function valueMutated(target, key) {
|
|
|
199
400
|
if (!isUndefined$1(reactiveObservers)) {
|
|
200
401
|
for (let i = 0, len = reactiveObservers.length; i < len; i += 1) {
|
|
201
402
|
const ro = reactiveObservers[i];
|
|
403
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
404
|
+
logMutation(ro, target, key);
|
|
405
|
+
}
|
|
202
406
|
ro.notify();
|
|
203
407
|
}
|
|
204
408
|
}
|
|
@@ -358,7 +562,7 @@ class SignalTracker {
|
|
|
358
562
|
}
|
|
359
563
|
|
|
360
564
|
/*
|
|
361
|
-
* Copyright (c)
|
|
565
|
+
* Copyright (c) 2024, Salesforce, Inc.
|
|
362
566
|
* All rights reserved.
|
|
363
567
|
* SPDX-License-Identifier: MIT
|
|
364
568
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
@@ -403,108 +607,6 @@ function createReactiveObserver(callback) {
|
|
|
403
607
|
return process.env.IS_BROWSER ? new ReactiveObserver(callback) : DUMMY_REACTIVE_OBSERVER;
|
|
404
608
|
}
|
|
405
609
|
|
|
406
|
-
/*
|
|
407
|
-
* Copyright (c) 2018, salesforce.com, inc.
|
|
408
|
-
* All rights reserved.
|
|
409
|
-
* SPDX-License-Identifier: MIT
|
|
410
|
-
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
411
|
-
*/
|
|
412
|
-
let nextTickCallbackQueue = [];
|
|
413
|
-
const SPACE_CHAR = 32;
|
|
414
|
-
const EmptyObject = seal(create(null));
|
|
415
|
-
const EmptyArray = seal([]);
|
|
416
|
-
function flushCallbackQueue() {
|
|
417
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
418
|
-
if (nextTickCallbackQueue.length === 0) {
|
|
419
|
-
throw new Error(`Internal Error: If callbackQueue is scheduled, it is because there must be at least one callback on this pending queue.`);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
const callbacks = nextTickCallbackQueue;
|
|
423
|
-
nextTickCallbackQueue = []; // reset to a new queue
|
|
424
|
-
for (let i = 0, len = callbacks.length; i < len; i += 1) {
|
|
425
|
-
callbacks[i]();
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
function addCallbackToNextTick(callback) {
|
|
429
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
430
|
-
if (!isFunction$1(callback)) {
|
|
431
|
-
throw new Error(`Internal Error: addCallbackToNextTick() can only accept a function callback`);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
if (nextTickCallbackQueue.length === 0) {
|
|
435
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
436
|
-
Promise.resolve().then(flushCallbackQueue);
|
|
437
|
-
}
|
|
438
|
-
ArrayPush$1.call(nextTickCallbackQueue, callback);
|
|
439
|
-
}
|
|
440
|
-
function guid() {
|
|
441
|
-
function s4() {
|
|
442
|
-
return Math.floor((1 + Math.random()) * 0x10000)
|
|
443
|
-
.toString(16)
|
|
444
|
-
.substring(1);
|
|
445
|
-
}
|
|
446
|
-
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
|
447
|
-
}
|
|
448
|
-
// Borrowed from Vue template compiler.
|
|
449
|
-
// https://github.com/vuejs/vue/blob/531371b818b0e31a989a06df43789728f23dc4e8/src/platforms/web/util/style.js#L5-L16
|
|
450
|
-
const DECLARATION_DELIMITER = /;(?![^(]*\))/g;
|
|
451
|
-
const PROPERTY_DELIMITER = /:(.+)/;
|
|
452
|
-
function parseStyleText(cssText) {
|
|
453
|
-
const styleMap = {};
|
|
454
|
-
const declarations = cssText.split(DECLARATION_DELIMITER);
|
|
455
|
-
for (const declaration of declarations) {
|
|
456
|
-
if (declaration) {
|
|
457
|
-
const [prop, value] = declaration.split(PROPERTY_DELIMITER);
|
|
458
|
-
if (prop !== undefined && value !== undefined) {
|
|
459
|
-
styleMap[prop.trim()] = value.trim();
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return styleMap;
|
|
464
|
-
}
|
|
465
|
-
// Make a shallow copy of an object but omit the given key
|
|
466
|
-
function cloneAndOmitKey(object, keyToOmit) {
|
|
467
|
-
const result = {};
|
|
468
|
-
for (const key of keys(object)) {
|
|
469
|
-
if (key !== keyToOmit) {
|
|
470
|
-
result[key] = object[key];
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return result;
|
|
474
|
-
}
|
|
475
|
-
function flattenStylesheets(stylesheets) {
|
|
476
|
-
const list = [];
|
|
477
|
-
for (const stylesheet of stylesheets) {
|
|
478
|
-
if (!isArray$1(stylesheet)) {
|
|
479
|
-
list.push(stylesheet);
|
|
480
|
-
}
|
|
481
|
-
else {
|
|
482
|
-
list.push(...flattenStylesheets(stylesheet));
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return list;
|
|
486
|
-
}
|
|
487
|
-
// Throw an error if we're running in prod mode. Ensures code is truly removed from prod mode.
|
|
488
|
-
function assertNotProd() {
|
|
489
|
-
/* istanbul ignore if */
|
|
490
|
-
if (process.env.NODE_ENV === 'production') {
|
|
491
|
-
// this method should never leak to prod
|
|
492
|
-
throw new ReferenceError();
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
function shouldBeFormAssociated(Ctor) {
|
|
496
|
-
const ctorFormAssociated = Boolean(Ctor.formAssociated);
|
|
497
|
-
const apiVersion = getComponentAPIVersion(Ctor);
|
|
498
|
-
const apiFeatureEnabled = isAPIFeatureEnabled(7 /* APIFeature.ENABLE_ELEMENT_INTERNALS_AND_FACE */, apiVersion);
|
|
499
|
-
if (process.env.NODE_ENV !== 'production' && ctorFormAssociated && !apiFeatureEnabled) {
|
|
500
|
-
const tagName = getComponentRegisteredName(Ctor);
|
|
501
|
-
logWarnOnce(`Component <${tagName}> set static formAssociated to true, but form ` +
|
|
502
|
-
`association is not enabled because the API version is ${apiVersion}. To enable form association, ` +
|
|
503
|
-
`update the LWC component API version to 61 or above. https://lwc.dev/guide/versioning`);
|
|
504
|
-
}
|
|
505
|
-
return ctorFormAssociated && apiFeatureEnabled;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
610
|
/*
|
|
509
611
|
* Copyright (c) 2020, salesforce.com, inc.
|
|
510
612
|
* All rights reserved.
|
|
@@ -2117,6 +2219,9 @@ function createConfigWatcher(component, configCallback, callbackWhenConfigIsRead
|
|
|
2117
2219
|
});
|
|
2118
2220
|
}
|
|
2119
2221
|
});
|
|
2222
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2223
|
+
associateReactiveObserverWithVM(ro, getAssociatedVM(component));
|
|
2224
|
+
}
|
|
2120
2225
|
const computeConfigAndUpdate = () => {
|
|
2121
2226
|
let config;
|
|
2122
2227
|
ro.observe(() => (config = configCallback(component)));
|
|
@@ -2405,6 +2510,9 @@ function internalTrackDecorator(key) {
|
|
|
2405
2510
|
}
|
|
2406
2511
|
}
|
|
2407
2512
|
const reactiveOrAnyValue = getReactiveProxy(newValue);
|
|
2513
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2514
|
+
trackTargetForMutationLogging(key, newValue);
|
|
2515
|
+
}
|
|
2408
2516
|
updateComponentValue(vm, key, reactiveOrAnyValue);
|
|
2409
2517
|
},
|
|
2410
2518
|
enumerable: true,
|
|
@@ -5690,7 +5798,7 @@ const api = freeze({
|
|
|
5690
5798
|
});
|
|
5691
5799
|
|
|
5692
5800
|
/*
|
|
5693
|
-
* Copyright (c)
|
|
5801
|
+
* Copyright (c) 2024, Salesforce, Inc.
|
|
5694
5802
|
* All rights reserved.
|
|
5695
5803
|
* SPDX-License-Identifier: MIT
|
|
5696
5804
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
@@ -5706,6 +5814,26 @@ const operationIdNameMapping = [
|
|
|
5706
5814
|
'lwc-hydrate',
|
|
5707
5815
|
'lwc-rehydrate',
|
|
5708
5816
|
];
|
|
5817
|
+
const operationTooltipMapping = [
|
|
5818
|
+
// constructor
|
|
5819
|
+
'component constructor()',
|
|
5820
|
+
// render
|
|
5821
|
+
'component render() and virtual DOM rendered',
|
|
5822
|
+
// patch
|
|
5823
|
+
'component DOM rendered',
|
|
5824
|
+
// connectedCallback
|
|
5825
|
+
'component connectedCallback()',
|
|
5826
|
+
// renderedCallback
|
|
5827
|
+
'component renderedCallback()',
|
|
5828
|
+
// disconnectedCallback
|
|
5829
|
+
'component disconnectedCallback()',
|
|
5830
|
+
// errorCallback
|
|
5831
|
+
'component errorCallback()',
|
|
5832
|
+
// lwc-hydrate
|
|
5833
|
+
'component first rendered',
|
|
5834
|
+
// lwc-rehydrate
|
|
5835
|
+
'component re-rendered',
|
|
5836
|
+
];
|
|
5709
5837
|
// Even if all the browser the engine supports implements the UserTiming API, we need to guard the measure APIs.
|
|
5710
5838
|
// JSDom (used in Jest) for example doesn't implement the UserTiming APIs.
|
|
5711
5839
|
const isUserTimingSupported = typeof performance !== 'undefined' &&
|
|
@@ -5720,8 +5848,17 @@ const start = !isUserTimingSupported
|
|
|
5720
5848
|
};
|
|
5721
5849
|
const end = !isUserTimingSupported
|
|
5722
5850
|
? noop
|
|
5723
|
-
: (measureName, markName) => {
|
|
5724
|
-
performance.measure(measureName,
|
|
5851
|
+
: (measureName, markName, devtools) => {
|
|
5852
|
+
performance.measure(measureName, {
|
|
5853
|
+
start: markName,
|
|
5854
|
+
detail: {
|
|
5855
|
+
devtools: {
|
|
5856
|
+
dataType: 'track-entry',
|
|
5857
|
+
track: '⚡️ Lightning Web Components',
|
|
5858
|
+
...devtools,
|
|
5859
|
+
},
|
|
5860
|
+
},
|
|
5861
|
+
});
|
|
5725
5862
|
// Clear the created marks and measure to avoid filling the performance entries buffer.
|
|
5726
5863
|
// Note: Even if the entries get deleted, existing PerformanceObservers preserve a copy of those entries.
|
|
5727
5864
|
performance.clearMarks(markName);
|
|
@@ -5738,6 +5875,66 @@ function getMarkName(opId, vm) {
|
|
|
5738
5875
|
// the right measures for components that are recursive.
|
|
5739
5876
|
return `${getMeasureName(opId, vm)} - ${vm.idx}`;
|
|
5740
5877
|
}
|
|
5878
|
+
function getProperties(vm) {
|
|
5879
|
+
return [
|
|
5880
|
+
['Tag Name', vm.tagName],
|
|
5881
|
+
['Component ID', String(vm.idx)],
|
|
5882
|
+
['Render Mode', vm.renderMode === 0 /* RenderMode.Light */ ? 'light DOM' : 'shadow DOM'],
|
|
5883
|
+
['Shadow Mode', vm.shadowMode === 0 /* ShadowMode.Native */ ? 'native' : 'synthetic'],
|
|
5884
|
+
];
|
|
5885
|
+
}
|
|
5886
|
+
// Create a list of tag names to the properties that were mutated, to help answer the question of
|
|
5887
|
+
// "why did this component re-render?"
|
|
5888
|
+
function getMutationProperties(mutationLogs) {
|
|
5889
|
+
// `mutationLogs` should never have length 0, but bail out if it does for whatever reason
|
|
5890
|
+
if (isUndefined$1(mutationLogs)) {
|
|
5891
|
+
return EmptyArray;
|
|
5892
|
+
}
|
|
5893
|
+
if (!mutationLogs.length) {
|
|
5894
|
+
// Currently this only occurs for experimental signals, because those mutations are not triggered by accessors
|
|
5895
|
+
// TODO [#4546]: support signals in mutation logging
|
|
5896
|
+
return EmptyArray;
|
|
5897
|
+
}
|
|
5898
|
+
// Keep track of unique IDs per tag name so we can just report a raw count at the end, e.g.
|
|
5899
|
+
// `<x-foo> (x2)` to indicate that two instances of `<x-foo>` were rendered.
|
|
5900
|
+
const tagNamesToIdsAndProps = new Map();
|
|
5901
|
+
for (const { vm: { tagName, idx }, prop, } of mutationLogs) {
|
|
5902
|
+
let idsAndProps = tagNamesToIdsAndProps.get(tagName);
|
|
5903
|
+
if (isUndefined$1(idsAndProps)) {
|
|
5904
|
+
idsAndProps = { ids: new Set(), keys: new Set() };
|
|
5905
|
+
tagNamesToIdsAndProps.set(tagName, idsAndProps);
|
|
5906
|
+
}
|
|
5907
|
+
idsAndProps.ids.add(idx);
|
|
5908
|
+
idsAndProps.keys.add(prop);
|
|
5909
|
+
}
|
|
5910
|
+
// Sort by tag name
|
|
5911
|
+
const entries = ArraySort.call([...tagNamesToIdsAndProps], (a, b) => a[0].localeCompare(b[0]));
|
|
5912
|
+
const tagNames = ArrayMap.call(entries, (item) => item[0]);
|
|
5913
|
+
// Show e.g. `<x-foo>` for one instance, or `<x-foo> (x2)` for two instances. (\u00D7 is multiplication symbol)
|
|
5914
|
+
const tagNamesToDisplayTagNames = new Map();
|
|
5915
|
+
for (const tagName of tagNames) {
|
|
5916
|
+
const { ids } = tagNamesToIdsAndProps.get(tagName);
|
|
5917
|
+
const displayTagName = `<${tagName}>${ids.size > 1 ? ` (\u00D7${ids.size})` : ''}`;
|
|
5918
|
+
tagNamesToDisplayTagNames.set(tagName, displayTagName);
|
|
5919
|
+
}
|
|
5920
|
+
// Summary row
|
|
5921
|
+
const usePlural = tagNames.length > 1 || tagNamesToIdsAndProps.get(tagNames[0]).ids.size > 1;
|
|
5922
|
+
const result = [
|
|
5923
|
+
[
|
|
5924
|
+
`Re-rendered Component${usePlural ? 's' : ''}`,
|
|
5925
|
+
ArrayJoin.call(ArrayMap.call(tagNames, (_) => tagNamesToDisplayTagNames.get(_)), ', '),
|
|
5926
|
+
],
|
|
5927
|
+
];
|
|
5928
|
+
// Detail rows
|
|
5929
|
+
for (const [prettyTagName, { keys }] of entries) {
|
|
5930
|
+
const displayTagName = tagNamesToDisplayTagNames.get(prettyTagName);
|
|
5931
|
+
ArrayPush$1.call(result, [displayTagName, ArrayJoin.call(ArraySort.call([...keys]), ', ')]);
|
|
5932
|
+
}
|
|
5933
|
+
return result;
|
|
5934
|
+
}
|
|
5935
|
+
function getTooltipText(measureName, opId) {
|
|
5936
|
+
return `${measureName} - ${operationTooltipMapping[opId]}`;
|
|
5937
|
+
}
|
|
5741
5938
|
/** Indicates if operations should be logged via the User Timing API. */
|
|
5742
5939
|
const isMeasureEnabled = process.env.NODE_ENV !== 'production';
|
|
5743
5940
|
/** Indicates if operations should be logged by the profiler. */
|
|
@@ -5775,30 +5972,61 @@ function logOperationEnd(opId, vm) {
|
|
|
5775
5972
|
if (isMeasureEnabled) {
|
|
5776
5973
|
const markName = getMarkName(opId, vm);
|
|
5777
5974
|
const measureName = getMeasureName(opId, vm);
|
|
5778
|
-
end(measureName, markName
|
|
5975
|
+
end(measureName, markName, {
|
|
5976
|
+
color: opId === 1 /* OperationId.Render */ ? 'primary' : 'secondary',
|
|
5977
|
+
tooltipText: getTooltipText(measureName, opId),
|
|
5978
|
+
properties: getProperties(vm),
|
|
5979
|
+
});
|
|
5779
5980
|
}
|
|
5780
5981
|
if (isProfilerEnabled) {
|
|
5781
5982
|
currentDispatcher(opId, 1 /* Phase.Stop */, vm.tagName, vm.idx, vm.renderMode, vm.shadowMode);
|
|
5782
5983
|
}
|
|
5783
5984
|
}
|
|
5784
|
-
function logGlobalOperationStart(opId
|
|
5985
|
+
function logGlobalOperationStart(opId) {
|
|
5785
5986
|
if (isMeasureEnabled) {
|
|
5786
|
-
const
|
|
5787
|
-
|
|
5987
|
+
const markName = getOperationName(opId);
|
|
5988
|
+
start(markName);
|
|
5989
|
+
}
|
|
5990
|
+
if (isProfilerEnabled) {
|
|
5991
|
+
currentDispatcher(opId, 0 /* Phase.Start */);
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
function logGlobalOperationStartWithVM(opId, vm) {
|
|
5995
|
+
if (isMeasureEnabled) {
|
|
5996
|
+
const markName = getMarkName(opId, vm);
|
|
5788
5997
|
start(markName);
|
|
5789
5998
|
}
|
|
5790
5999
|
if (isProfilerEnabled) {
|
|
5791
|
-
currentDispatcher(opId, 0 /* Phase.Start */, vm
|
|
6000
|
+
currentDispatcher(opId, 0 /* Phase.Start */, vm.tagName, vm.idx, vm.renderMode, vm.shadowMode);
|
|
6001
|
+
}
|
|
6002
|
+
}
|
|
6003
|
+
function logGlobalOperationEnd(opId, mutationLogs) {
|
|
6004
|
+
if (isMeasureEnabled) {
|
|
6005
|
+
const opName = getOperationName(opId);
|
|
6006
|
+
const markName = opName;
|
|
6007
|
+
end(opName, markName, {
|
|
6008
|
+
// not really an error, but we want to draw attention to re-renders since folks may want to debug it
|
|
6009
|
+
color: 'error',
|
|
6010
|
+
tooltipText: getTooltipText(opName, opId),
|
|
6011
|
+
properties: getMutationProperties(mutationLogs),
|
|
6012
|
+
});
|
|
6013
|
+
}
|
|
6014
|
+
if (isProfilerEnabled) {
|
|
6015
|
+
currentDispatcher(opId, 1 /* Phase.Stop */);
|
|
5792
6016
|
}
|
|
5793
6017
|
}
|
|
5794
|
-
function
|
|
6018
|
+
function logGlobalOperationEndWithVM(opId, vm) {
|
|
5795
6019
|
if (isMeasureEnabled) {
|
|
5796
6020
|
const opName = getOperationName(opId);
|
|
5797
|
-
const markName =
|
|
5798
|
-
end(opName, markName
|
|
6021
|
+
const markName = getMarkName(opId, vm);
|
|
6022
|
+
end(opName, markName, {
|
|
6023
|
+
color: 'tertiary',
|
|
6024
|
+
tooltipText: getTooltipText(opName, opId),
|
|
6025
|
+
properties: getProperties(vm),
|
|
6026
|
+
});
|
|
5799
6027
|
}
|
|
5800
6028
|
if (isProfilerEnabled) {
|
|
5801
|
-
currentDispatcher(opId, 1 /* Phase.Stop */, vm
|
|
6029
|
+
currentDispatcher(opId, 1 /* Phase.Stop */, vm.tagName, vm.idx, vm.renderMode, vm.shadowMode);
|
|
5802
6030
|
}
|
|
5803
6031
|
}
|
|
5804
6032
|
|
|
@@ -6306,13 +6534,17 @@ function getComponentAPIVersion(Ctor) {
|
|
|
6306
6534
|
return apiVersion;
|
|
6307
6535
|
}
|
|
6308
6536
|
function getTemplateReactiveObserver(vm) {
|
|
6309
|
-
|
|
6537
|
+
const reactiveObserver = createReactiveObserver(() => {
|
|
6310
6538
|
const { isDirty } = vm;
|
|
6311
6539
|
if (isFalse(isDirty)) {
|
|
6312
6540
|
markComponentAsDirty(vm);
|
|
6313
6541
|
scheduleRehydration(vm);
|
|
6314
6542
|
}
|
|
6315
6543
|
});
|
|
6544
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
6545
|
+
associateReactiveObserverWithVM(reactiveObserver, vm);
|
|
6546
|
+
}
|
|
6547
|
+
return reactiveObserver;
|
|
6316
6548
|
}
|
|
6317
6549
|
function resetTemplateObserverAndUnsubscribe(vm) {
|
|
6318
6550
|
const { tro, component } = vm;
|
|
@@ -6387,7 +6619,12 @@ function rerenderVM(vm) {
|
|
|
6387
6619
|
}
|
|
6388
6620
|
function connectRootElement(elm) {
|
|
6389
6621
|
const vm = getAssociatedVM(elm);
|
|
6390
|
-
|
|
6622
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
6623
|
+
// Flush any logs for this VM so that the initial properties from the constructor don't "count"
|
|
6624
|
+
// in subsequent re-renders (lwc-rehydrate). Right now we're at the first render (lwc-hydrate).
|
|
6625
|
+
flushMutationLogsForVM(vm);
|
|
6626
|
+
}
|
|
6627
|
+
logGlobalOperationStartWithVM(7 /* OperationId.GlobalHydrate */, vm);
|
|
6391
6628
|
// Usually means moving the element from one place to another, which is observable via
|
|
6392
6629
|
// life-cycle hooks.
|
|
6393
6630
|
if (vm.state === 1 /* VMState.connected */) {
|
|
@@ -6395,7 +6632,7 @@ function connectRootElement(elm) {
|
|
|
6395
6632
|
}
|
|
6396
6633
|
runConnectedCallback(vm);
|
|
6397
6634
|
rehydrate(vm);
|
|
6398
|
-
|
|
6635
|
+
logGlobalOperationEndWithVM(7 /* OperationId.GlobalHydrate */, vm);
|
|
6399
6636
|
}
|
|
6400
6637
|
function disconnectRootElement(elm) {
|
|
6401
6638
|
const vm = getAssociatedVM(elm);
|
|
@@ -6701,6 +6938,9 @@ function runRenderedCallback(vm) {
|
|
|
6701
6938
|
}
|
|
6702
6939
|
let rehydrateQueue = [];
|
|
6703
6940
|
function flushRehydrationQueue() {
|
|
6941
|
+
// Gather the logs before rehydration starts so they can be reported at the end of rehydration.
|
|
6942
|
+
// Note that we also clear all existing logs at this point so that subsequent re-renders start from a clean slate.
|
|
6943
|
+
const mutationLogs = process.env.NODE_ENV !== 'production' ? getAndFlushMutationLogs() : undefined;
|
|
6704
6944
|
logGlobalOperationStart(8 /* OperationId.GlobalRehydrate */);
|
|
6705
6945
|
if (process.env.NODE_ENV !== 'production') {
|
|
6706
6946
|
assert.invariant(rehydrateQueue.length, `If rehydrateQueue was scheduled, it is because there must be at least one VM on this pending queue instead of ${rehydrateQueue}.`);
|
|
@@ -6721,13 +6961,13 @@ function flushRehydrationQueue() {
|
|
|
6721
6961
|
ArrayUnshift.apply(rehydrateQueue, ArraySlice.call(vms, i + 1));
|
|
6722
6962
|
}
|
|
6723
6963
|
// we need to end the measure before throwing.
|
|
6724
|
-
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate
|
|
6964
|
+
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate */, mutationLogs);
|
|
6725
6965
|
// re-throwing the original error will break the current tick, but since the next tick is
|
|
6726
6966
|
// already scheduled, it should continue patching the rest.
|
|
6727
6967
|
throw error;
|
|
6728
6968
|
}
|
|
6729
6969
|
}
|
|
6730
|
-
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate
|
|
6970
|
+
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate */, mutationLogs);
|
|
6731
6971
|
}
|
|
6732
6972
|
function runConnectedCallback(vm) {
|
|
6733
6973
|
const { state } = vm;
|
|
@@ -8095,5 +8335,5 @@ function readonly(obj) {
|
|
|
8095
8335
|
}
|
|
8096
8336
|
|
|
8097
8337
|
export { LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, computeShadowAndRenderMode, connectRootElement, createContextProviderWithRegister, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentAPIVersion, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerTemplate, runFormAssociatedCallback, runFormDisabledCallback, runFormResetCallback, runFormStateRestoreCallback, sanitizeAttribute, setHooks, shouldBeFormAssociated, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
|
|
8098
|
-
/** version: 8.0.
|
|
8338
|
+
/** version: 8.1.0-alpha.1 */
|
|
8099
8339
|
//# sourceMappingURL=index.js.map
|