@lwc/engine-core 8.0.0-alpha.1 → 8.1.0-alpha.0
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 +371 -125
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +372 -126
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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
|
|
|
@@ -5854,6 +6082,12 @@ function getVMBeingRendered() {
|
|
|
5854
6082
|
function setVMBeingRendered(vm) {
|
|
5855
6083
|
vmBeingRendered = vm;
|
|
5856
6084
|
}
|
|
6085
|
+
const VALID_SCOPE_TOKEN_REGEX = /^[a-zA-Z0-9\-_.]+$/;
|
|
6086
|
+
// See W-16614556
|
|
6087
|
+
// TODO [#2826]: freeze the template object
|
|
6088
|
+
function isValidScopeToken(token) {
|
|
6089
|
+
return isString(token) && VALID_SCOPE_TOKEN_REGEX.test(token);
|
|
6090
|
+
}
|
|
5857
6091
|
function validateSlots(vm) {
|
|
5858
6092
|
assertNotProd(); // this method should never leak to prod
|
|
5859
6093
|
const { cmpSlots } = vm;
|
|
@@ -6006,9 +6240,9 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
6006
6240
|
}
|
|
6007
6241
|
}
|
|
6008
6242
|
// See W-16614556
|
|
6009
|
-
if ((hasStyleToken && !
|
|
6010
|
-
(hasLegacyToken && !
|
|
6011
|
-
throw new Error('stylesheet token must be a string');
|
|
6243
|
+
if ((hasStyleToken && !isValidScopeToken(stylesheetToken)) ||
|
|
6244
|
+
(hasLegacyToken && !isValidScopeToken(legacyStylesheetToken))) {
|
|
6245
|
+
throw new Error('stylesheet token must be a valid string');
|
|
6012
6246
|
}
|
|
6013
6247
|
// If legacy stylesheet tokens are required, then add them to the rendered string
|
|
6014
6248
|
const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
|
|
@@ -6300,13 +6534,17 @@ function getComponentAPIVersion(Ctor) {
|
|
|
6300
6534
|
return apiVersion;
|
|
6301
6535
|
}
|
|
6302
6536
|
function getTemplateReactiveObserver(vm) {
|
|
6303
|
-
|
|
6537
|
+
const reactiveObserver = createReactiveObserver(() => {
|
|
6304
6538
|
const { isDirty } = vm;
|
|
6305
6539
|
if (isFalse(isDirty)) {
|
|
6306
6540
|
markComponentAsDirty(vm);
|
|
6307
6541
|
scheduleRehydration(vm);
|
|
6308
6542
|
}
|
|
6309
6543
|
});
|
|
6544
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
6545
|
+
associateReactiveObserverWithVM(reactiveObserver, vm);
|
|
6546
|
+
}
|
|
6547
|
+
return reactiveObserver;
|
|
6310
6548
|
}
|
|
6311
6549
|
function resetTemplateObserverAndUnsubscribe(vm) {
|
|
6312
6550
|
const { tro, component } = vm;
|
|
@@ -6381,7 +6619,12 @@ function rerenderVM(vm) {
|
|
|
6381
6619
|
}
|
|
6382
6620
|
function connectRootElement(elm) {
|
|
6383
6621
|
const vm = getAssociatedVM(elm);
|
|
6384
|
-
|
|
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);
|
|
6385
6628
|
// Usually means moving the element from one place to another, which is observable via
|
|
6386
6629
|
// life-cycle hooks.
|
|
6387
6630
|
if (vm.state === 1 /* VMState.connected */) {
|
|
@@ -6389,7 +6632,7 @@ function connectRootElement(elm) {
|
|
|
6389
6632
|
}
|
|
6390
6633
|
runConnectedCallback(vm);
|
|
6391
6634
|
rehydrate(vm);
|
|
6392
|
-
|
|
6635
|
+
logGlobalOperationEndWithVM(7 /* OperationId.GlobalHydrate */, vm);
|
|
6393
6636
|
}
|
|
6394
6637
|
function disconnectRootElement(elm) {
|
|
6395
6638
|
const vm = getAssociatedVM(elm);
|
|
@@ -6695,6 +6938,9 @@ function runRenderedCallback(vm) {
|
|
|
6695
6938
|
}
|
|
6696
6939
|
let rehydrateQueue = [];
|
|
6697
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;
|
|
6698
6944
|
logGlobalOperationStart(8 /* OperationId.GlobalRehydrate */);
|
|
6699
6945
|
if (process.env.NODE_ENV !== 'production') {
|
|
6700
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}.`);
|
|
@@ -6715,13 +6961,13 @@ function flushRehydrationQueue() {
|
|
|
6715
6961
|
ArrayUnshift.apply(rehydrateQueue, ArraySlice.call(vms, i + 1));
|
|
6716
6962
|
}
|
|
6717
6963
|
// we need to end the measure before throwing.
|
|
6718
|
-
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate
|
|
6964
|
+
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate */, mutationLogs);
|
|
6719
6965
|
// re-throwing the original error will break the current tick, but since the next tick is
|
|
6720
6966
|
// already scheduled, it should continue patching the rest.
|
|
6721
6967
|
throw error;
|
|
6722
6968
|
}
|
|
6723
6969
|
}
|
|
6724
|
-
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate
|
|
6970
|
+
logGlobalOperationEnd(8 /* OperationId.GlobalRehydrate */, mutationLogs);
|
|
6725
6971
|
}
|
|
6726
6972
|
function runConnectedCallback(vm) {
|
|
6727
6973
|
const { state } = vm;
|
|
@@ -8089,5 +8335,5 @@ function readonly(obj) {
|
|
|
8089
8335
|
}
|
|
8090
8336
|
|
|
8091
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 };
|
|
8092
|
-
/** version: 8.0.0
|
|
8338
|
+
/** version: 8.0.0 */
|
|
8093
8339
|
//# sourceMappingURL=index.js.map
|