@lwc/engine-core 2.32.1 → 2.33.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.
@@ -3,6 +3,7 @@
3
3
 
4
4
  var features = require('@lwc/features');
5
5
  var shared = require('@lwc/shared');
6
+ var ariaReflection = require('@lwc/aria-reflection');
6
7
 
7
8
  /*
8
9
  * Copyright (c) 2018, salesforce.com, inc.
@@ -1410,46 +1411,51 @@ function markLockerLiveObject(obj) {
1410
1411
  * for the Base Lightning Element, it also include the reactivity bit, so the standard property is reactive.
1411
1412
  */
1412
1413
  function createBridgeToElementDescriptor(propName, descriptor) {
1413
- const { get, set, enumerable, configurable } = descriptor;
1414
- if (!shared.isFunction(get)) {
1415
- if (process.env.NODE_ENV !== 'production') {
1416
- shared.assert.fail(`Detected invalid public property descriptor for HTMLElement.prototype.${propName} definition. Missing the standard getter.`);
1417
- }
1418
- throw new TypeError();
1414
+ const {
1415
+ get,
1416
+ set,
1417
+ enumerable,
1418
+ configurable
1419
+ } = descriptor;
1420
+ if (!shared.isFunction(get)) {
1421
+ if (process.env.NODE_ENV !== 'production') {
1422
+ shared.assert.fail(`Detected invalid public property descriptor for HTMLElement.prototype.${propName} definition. Missing the standard getter.`);
1419
1423
  }
1420
- if (!shared.isFunction(set)) {
1424
+ throw new TypeError();
1425
+ }
1426
+ if (!shared.isFunction(set)) {
1427
+ if (process.env.NODE_ENV !== 'production') {
1428
+ shared.assert.fail(`Detected invalid public property descriptor for HTMLElement.prototype.${propName} definition. Missing the standard setter.`);
1429
+ }
1430
+ throw new TypeError();
1431
+ }
1432
+ return {
1433
+ enumerable,
1434
+ configurable,
1435
+ get() {
1436
+ const vm = getAssociatedVM(this);
1437
+ if (isBeingConstructed(vm)) {
1421
1438
  if (process.env.NODE_ENV !== 'production') {
1422
- shared.assert.fail(`Detected invalid public property descriptor for HTMLElement.prototype.${propName} definition. Missing the standard setter.`);
1439
+ logError(`The value of property \`${propName}\` can't be read from the constructor because the owner component hasn't set the value yet. Instead, use the constructor to set a default value for the property.`, vm);
1423
1440
  }
1424
- throw new TypeError();
1441
+ return;
1442
+ }
1443
+ componentValueObserved(vm, propName);
1444
+ return get.call(vm.elm);
1445
+ },
1446
+ set(newValue) {
1447
+ const vm = getAssociatedVM(this);
1448
+ if (process.env.NODE_ENV !== 'production') {
1449
+ const vmBeingRendered = getVMBeingRendered();
1450
+ shared.assert.invariant(!isInvokingRender, `${vmBeingRendered}.render() method has side effects on the state of ${vm}.${propName}`);
1451
+ shared.assert.invariant(!isUpdatingTemplate, `When updating the template of ${vmBeingRendered}, one of the accessors used by the template has side effects on the state of ${vm}.${propName}`);
1452
+ shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1453
+ shared.assert.invariant(!shared.isObject(newValue) || shared.isNull(newValue), `Invalid value "${newValue}" for "${propName}" of ${vm}. Value cannot be an object, must be a primitive value.`);
1454
+ }
1455
+ updateComponentValue(vm, propName, newValue);
1456
+ return set.call(vm.elm, newValue);
1425
1457
  }
1426
- return {
1427
- enumerable,
1428
- configurable,
1429
- get() {
1430
- const vm = getAssociatedVM(this);
1431
- if (isBeingConstructed(vm)) {
1432
- if (process.env.NODE_ENV !== 'production') {
1433
- logError(`The value of property \`${propName}\` can't be read from the constructor because the owner component hasn't set the value yet. Instead, use the constructor to set a default value for the property.`, vm);
1434
- }
1435
- return;
1436
- }
1437
- componentValueObserved(vm, propName);
1438
- return get.call(vm.elm);
1439
- },
1440
- set(newValue) {
1441
- const vm = getAssociatedVM(this);
1442
- if (process.env.NODE_ENV !== 'production') {
1443
- const vmBeingRendered = getVMBeingRendered();
1444
- shared.assert.invariant(!isInvokingRender, `${vmBeingRendered}.render() method has side effects on the state of ${vm}.${propName}`);
1445
- shared.assert.invariant(!isUpdatingTemplate, `When updating the template of ${vmBeingRendered}, one of the accessors used by the template has side effects on the state of ${vm}.${propName}`);
1446
- shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1447
- shared.assert.invariant(!shared.isObject(newValue) || shared.isNull(newValue), `Invalid value "${newValue}" for "${propName}" of ${vm}. Value cannot be an object, must be a primitive value.`);
1448
- }
1449
- updateComponentValue(vm, propName, newValue);
1450
- return set.call(vm.elm, newValue);
1451
- },
1452
- };
1458
+ };
1453
1459
  }
1454
1460
  const EMPTY_REFS = shared.freeze(shared.create(null));
1455
1461
  const refsCache = new WeakMap();
@@ -1459,345 +1465,444 @@ const refsCache = new WeakMap();
1459
1465
  **/
1460
1466
  // @ts-ignore
1461
1467
  const LightningElement = function () {
1462
- // This should be as performant as possible, while any initialization should be done lazily
1463
- if (shared.isNull(vmBeingConstructed)) {
1464
- // Thrown when doing something like `new LightningElement()` or
1465
- // `class Foo extends LightningElement {}; new Foo()`
1466
- throw new TypeError('Illegal constructor');
1467
- }
1468
- const vm = vmBeingConstructed;
1469
- const { def, elm } = vm;
1470
- const { bridge } = def;
1468
+ // This should be as performant as possible, while any initialization should be done lazily
1469
+ if (shared.isNull(vmBeingConstructed)) {
1470
+ // Thrown when doing something like `new LightningElement()` or
1471
+ // `class Foo extends LightningElement {}; new Foo()`
1472
+ throw new TypeError('Illegal constructor');
1473
+ }
1474
+ const vm = vmBeingConstructed;
1475
+ const {
1476
+ def,
1477
+ elm
1478
+ } = vm;
1479
+ const {
1480
+ bridge
1481
+ } = def;
1482
+ if (process.env.NODE_ENV !== 'production') {
1483
+ const {
1484
+ assertInstanceOfHTMLElement
1485
+ } = vm.renderer;
1486
+ assertInstanceOfHTMLElement(vm.elm, `Component creation requires a DOM element to be associated to ${vm}.`);
1487
+ }
1488
+ const component = this;
1489
+ shared.setPrototypeOf(elm, bridge.prototype);
1490
+ vm.component = this;
1491
+ // Locker hooks assignment. When the LWC engine run with Locker, Locker intercepts all the new
1492
+ // component creation and passes hooks to instrument all the component interactions with the
1493
+ // engine. We are intentionally hiding this argument from the formal API of LightningElement
1494
+ // because we don't want folks to know about it just yet.
1495
+ if (arguments.length === 1) {
1496
+ const {
1497
+ callHook,
1498
+ setHook,
1499
+ getHook
1500
+ } = arguments[0];
1501
+ vm.callHook = callHook;
1502
+ vm.setHook = setHook;
1503
+ vm.getHook = getHook;
1504
+ }
1505
+ markLockerLiveObject(this);
1506
+ // Linking elm, shadow root and component with the VM.
1507
+ associateVM(component, vm);
1508
+ associateVM(elm, vm);
1509
+ if (vm.renderMode === 1 /* RenderMode.Shadow */) {
1510
+ vm.renderRoot = doAttachShadow(vm);
1511
+ } else {
1512
+ vm.renderRoot = elm;
1513
+ }
1514
+ // Adding extra guard rails in DEV mode.
1515
+ if (process.env.NODE_ENV !== 'production') {
1516
+ patchCustomElementWithRestrictions(elm);
1517
+ patchComponentWithRestrictions(component);
1518
+ }
1519
+ return this;
1520
+ };
1521
+ function doAttachShadow(vm) {
1522
+ const {
1523
+ elm,
1524
+ mode,
1525
+ shadowMode,
1526
+ def: {
1527
+ ctor
1528
+ },
1529
+ renderer: {
1530
+ attachShadow
1531
+ }
1532
+ } = vm;
1533
+ const shadowRoot = attachShadow(elm, {
1534
+ [shared.KEY__SYNTHETIC_MODE]: shadowMode === 1 /* ShadowMode.Synthetic */,
1535
+ delegatesFocus: Boolean(ctor.delegatesFocus),
1536
+ mode
1537
+ });
1538
+ vm.shadowRoot = shadowRoot;
1539
+ associateVM(shadowRoot, vm);
1540
+ if (process.env.NODE_ENV !== 'production') {
1541
+ patchShadowRootWithRestrictions(shadowRoot);
1542
+ }
1543
+ return shadowRoot;
1544
+ }
1545
+ function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
1546
+ if (isBeingConstructed(vm)) {
1547
+ logError(`this.${methodOrPropName} should not be called during the construction of the custom element for ${getComponentTag(vm)} because the element is not yet in the DOM or has no children yet.`);
1548
+ }
1549
+ }
1550
+ // @ts-ignore
1551
+ LightningElement.prototype = {
1552
+ constructor: LightningElement,
1553
+ dispatchEvent(event) {
1554
+ const vm = getAssociatedVM(this);
1555
+ const {
1556
+ elm,
1557
+ renderer: {
1558
+ dispatchEvent
1559
+ }
1560
+ } = vm;
1561
+ return dispatchEvent(elm, event);
1562
+ },
1563
+ addEventListener(type, listener, options) {
1564
+ const vm = getAssociatedVM(this);
1565
+ const {
1566
+ elm,
1567
+ renderer: {
1568
+ addEventListener
1569
+ }
1570
+ } = vm;
1471
1571
  if (process.env.NODE_ENV !== 'production') {
1472
- const { assertInstanceOfHTMLElement } = vm.renderer;
1473
- assertInstanceOfHTMLElement(vm.elm, `Component creation requires a DOM element to be associated to ${vm}.`);
1474
- }
1475
- const component = this;
1476
- shared.setPrototypeOf(elm, bridge.prototype);
1477
- vm.component = this;
1478
- // Locker hooks assignment. When the LWC engine run with Locker, Locker intercepts all the new
1479
- // component creation and passes hooks to instrument all the component interactions with the
1480
- // engine. We are intentionally hiding this argument from the formal API of LightningElement
1481
- // because we don't want folks to know about it just yet.
1482
- if (arguments.length === 1) {
1483
- const { callHook, setHook, getHook } = arguments[0];
1484
- vm.callHook = callHook;
1485
- vm.setHook = setHook;
1486
- vm.getHook = getHook;
1487
- }
1488
- markLockerLiveObject(this);
1489
- // Linking elm, shadow root and component with the VM.
1490
- associateVM(component, vm);
1491
- associateVM(elm, vm);
1492
- if (vm.renderMode === 1 /* RenderMode.Shadow */) {
1493
- vm.renderRoot = doAttachShadow(vm);
1572
+ const vmBeingRendered = getVMBeingRendered();
1573
+ shared.assert.invariant(!isInvokingRender, `${vmBeingRendered}.render() method has side effects on the state of ${vm} by adding an event listener for "${type}".`);
1574
+ shared.assert.invariant(!isUpdatingTemplate, `Updating the template of ${vmBeingRendered} has side effects on the state of ${vm} by adding an event listener for "${type}".`);
1575
+ shared.assert.invariant(shared.isFunction(listener), `Invalid second argument for this.addEventListener() in ${vm} for event "${type}". Expected an EventListener but received ${listener}.`);
1576
+ }
1577
+ const wrappedListener = getWrappedComponentsListener(vm, listener);
1578
+ addEventListener(elm, type, wrappedListener, options);
1579
+ },
1580
+ removeEventListener(type, listener, options) {
1581
+ const vm = getAssociatedVM(this);
1582
+ const {
1583
+ elm,
1584
+ renderer: {
1585
+ removeEventListener
1586
+ }
1587
+ } = vm;
1588
+ const wrappedListener = getWrappedComponentsListener(vm, listener);
1589
+ removeEventListener(elm, type, wrappedListener, options);
1590
+ },
1591
+ hasAttribute(name) {
1592
+ const vm = getAssociatedVM(this);
1593
+ const {
1594
+ elm,
1595
+ renderer: {
1596
+ getAttribute
1597
+ }
1598
+ } = vm;
1599
+ return !shared.isNull(getAttribute(elm, name));
1600
+ },
1601
+ hasAttributeNS(namespace, name) {
1602
+ const vm = getAssociatedVM(this);
1603
+ const {
1604
+ elm,
1605
+ renderer: {
1606
+ getAttribute
1607
+ }
1608
+ } = vm;
1609
+ return !shared.isNull(getAttribute(elm, name, namespace));
1610
+ },
1611
+ removeAttribute(name) {
1612
+ const vm = getAssociatedVM(this);
1613
+ const {
1614
+ elm,
1615
+ renderer: {
1616
+ removeAttribute
1617
+ }
1618
+ } = vm;
1619
+ unlockAttribute(elm, name);
1620
+ removeAttribute(elm, name);
1621
+ lockAttribute();
1622
+ },
1623
+ removeAttributeNS(namespace, name) {
1624
+ const {
1625
+ elm,
1626
+ renderer: {
1627
+ removeAttribute
1628
+ }
1629
+ } = getAssociatedVM(this);
1630
+ unlockAttribute(elm, name);
1631
+ removeAttribute(elm, name, namespace);
1632
+ lockAttribute();
1633
+ },
1634
+ getAttribute(name) {
1635
+ const vm = getAssociatedVM(this);
1636
+ const {
1637
+ elm
1638
+ } = vm;
1639
+ const {
1640
+ getAttribute
1641
+ } = vm.renderer;
1642
+ return getAttribute(elm, name);
1643
+ },
1644
+ getAttributeNS(namespace, name) {
1645
+ const vm = getAssociatedVM(this);
1646
+ const {
1647
+ elm
1648
+ } = vm;
1649
+ const {
1650
+ getAttribute
1651
+ } = vm.renderer;
1652
+ return getAttribute(elm, name, namespace);
1653
+ },
1654
+ setAttribute(name, value) {
1655
+ const vm = getAssociatedVM(this);
1656
+ const {
1657
+ elm,
1658
+ renderer: {
1659
+ setAttribute
1660
+ }
1661
+ } = vm;
1662
+ if (process.env.NODE_ENV !== 'production') {
1663
+ shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1664
+ }
1665
+ unlockAttribute(elm, name);
1666
+ setAttribute(elm, name, value);
1667
+ lockAttribute();
1668
+ },
1669
+ setAttributeNS(namespace, name, value) {
1670
+ const vm = getAssociatedVM(this);
1671
+ const {
1672
+ elm,
1673
+ renderer: {
1674
+ setAttribute
1675
+ }
1676
+ } = vm;
1677
+ if (process.env.NODE_ENV !== 'production') {
1678
+ shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1679
+ }
1680
+ unlockAttribute(elm, name);
1681
+ setAttribute(elm, name, value, namespace);
1682
+ lockAttribute();
1683
+ },
1684
+ getBoundingClientRect() {
1685
+ const vm = getAssociatedVM(this);
1686
+ const {
1687
+ elm,
1688
+ renderer: {
1689
+ getBoundingClientRect
1690
+ }
1691
+ } = vm;
1692
+ if (process.env.NODE_ENV !== 'production') {
1693
+ warnIfInvokedDuringConstruction(vm, 'getBoundingClientRect()');
1494
1694
  }
1495
- else {
1496
- vm.renderRoot = elm;
1695
+ return getBoundingClientRect(elm);
1696
+ },
1697
+ get isConnected() {
1698
+ const vm = getAssociatedVM(this);
1699
+ const {
1700
+ elm,
1701
+ renderer: {
1702
+ isConnected
1703
+ }
1704
+ } = vm;
1705
+ return isConnected(elm);
1706
+ },
1707
+ get classList() {
1708
+ const vm = getAssociatedVM(this);
1709
+ const {
1710
+ elm,
1711
+ renderer: {
1712
+ getClassList
1713
+ }
1714
+ } = vm;
1715
+ if (process.env.NODE_ENV !== 'production') {
1716
+ // TODO [#1290]: this still fails in dev but works in production, eventually, we should
1717
+ // just throw in all modes
1718
+ shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct ${vm}: The result must not have attributes. Adding or tampering with classname in constructor is not allowed in a web component, use connectedCallback() instead.`);
1719
+ }
1720
+ return getClassList(elm);
1721
+ },
1722
+ get template() {
1723
+ const vm = getAssociatedVM(this);
1724
+ if (process.env.NODE_ENV !== 'production') {
1725
+ if (vm.renderMode === 0 /* RenderMode.Light */) {
1726
+ logError('`this.template` returns null for light DOM components. Since there is no shadow, the rendered content can be accessed via `this` itself. e.g. instead of `this.template.querySelector`, use `this.querySelector`.');
1727
+ }
1728
+ }
1729
+ return vm.shadowRoot;
1730
+ },
1731
+ get refs() {
1732
+ const vm = getAssociatedVM(this);
1733
+ if (isUpdatingTemplate) {
1734
+ if (process.env.NODE_ENV !== 'production') {
1735
+ logError(`this.refs should not be called while ${getComponentTag(vm)} is rendering. Use this.refs only when the DOM is stable, e.g. in renderedCallback().`);
1736
+ }
1737
+ // If the template is in the process of being updated, then we don't want to go through the normal
1738
+ // process of returning the refs and caching them, because the state of the refs is unstable.
1739
+ // This can happen if e.g. a template contains `<div class={foo}></div>` and `foo` is computed
1740
+ // based on `this.refs.bar`.
1741
+ return;
1497
1742
  }
1498
- // Adding extra guard rails in DEV mode.
1499
1743
  if (process.env.NODE_ENV !== 'production') {
1500
- patchCustomElementWithRestrictions(elm);
1501
- patchComponentWithRestrictions(component);
1744
+ warnIfInvokedDuringConstruction(vm, 'refs');
1502
1745
  }
1503
- return this;
1504
- };
1505
- function doAttachShadow(vm) {
1506
- const { elm, mode, shadowMode, def: { ctor }, renderer: { attachShadow }, } = vm;
1507
- const shadowRoot = attachShadow(elm, {
1508
- [shared.KEY__SYNTHETIC_MODE]: shadowMode === 1 /* ShadowMode.Synthetic */,
1509
- delegatesFocus: Boolean(ctor.delegatesFocus),
1510
- mode,
1746
+ const {
1747
+ refVNodes,
1748
+ hasRefVNodes,
1749
+ cmpTemplate
1750
+ } = vm;
1751
+ // If the `cmpTemplate` is null, that means that the template has not been rendered yet. Most likely this occurs
1752
+ // if `this.refs` is called during the `connectedCallback` phase. The DOM elements have not been rendered yet,
1753
+ // so log a warning. Note we also check `isBeingConstructed()` to avoid a double warning (due to
1754
+ // `warnIfInvokedDuringConstruction` above).
1755
+ if (process.env.NODE_ENV !== 'production' && shared.isNull(cmpTemplate) && !isBeingConstructed(vm)) {
1756
+ logError(`this.refs is undefined for ${getComponentTag(vm)}. This is either because the attached template has no "lwc:ref" directive, or this.refs was ` + `invoked before renderedCallback(). Use this.refs only when the referenced HTML elements have ` + `been rendered to the DOM, such as within renderedCallback() or disconnectedCallback().`);
1757
+ }
1758
+ // For backwards compatibility with component written before template refs
1759
+ // were introduced, we return undefined if the template has no refs defined
1760
+ // anywhere. This fixes components that may want to add an expando called `refs`
1761
+ // and are checking if it exists with `if (this.refs)` before adding it.
1762
+ // Note it is not sufficient to just check if `refVNodes` is null or empty,
1763
+ // because a template may have `lwc:ref` defined within a falsy `if:true` block.
1764
+ if (!hasRefVNodes) {
1765
+ return;
1766
+ }
1767
+ // For templates that are using `lwc:ref`, if there are no refs currently available
1768
+ // (e.g. refs inside of a falsy `if:true` block), we return an empty object.
1769
+ if (shared.isNull(refVNodes)) {
1770
+ return EMPTY_REFS;
1771
+ }
1772
+ // The refNodes can be cached based on the refVNodes, since the refVNodes
1773
+ // are recreated from scratch every time the template is rendered.
1774
+ // This happens with `vm.refVNodes = null` in `template.ts` in `@lwc/engine-core`.
1775
+ let refs = refsCache.get(refVNodes);
1776
+ if (shared.isUndefined(refs)) {
1777
+ refs = shared.create(null);
1778
+ for (const key of shared.keys(refVNodes)) {
1779
+ refs[key] = refVNodes[key].elm;
1780
+ }
1781
+ shared.freeze(refs);
1782
+ refsCache.set(refVNodes, refs);
1783
+ }
1784
+ return refs;
1785
+ },
1786
+ // For backwards compat, we allow component authors to set `refs` as an expando
1787
+ set refs(value) {
1788
+ shared.defineProperty(this, 'refs', {
1789
+ configurable: true,
1790
+ enumerable: true,
1791
+ writable: true,
1792
+ value
1511
1793
  });
1512
- vm.shadowRoot = shadowRoot;
1513
- associateVM(shadowRoot, vm);
1794
+ },
1795
+ get shadowRoot() {
1796
+ // From within the component instance, the shadowRoot is always reported as "closed".
1797
+ // Authors should rely on this.template instead.
1798
+ return null;
1799
+ },
1800
+ get children() {
1801
+ const vm = getAssociatedVM(this);
1802
+ const renderer = vm.renderer;
1514
1803
  if (process.env.NODE_ENV !== 'production') {
1515
- patchShadowRootWithRestrictions(shadowRoot);
1804
+ warnIfInvokedDuringConstruction(vm, 'children');
1516
1805
  }
1517
- return shadowRoot;
1518
- }
1519
- function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
1520
- if (isBeingConstructed(vm)) {
1521
- logError(`this.${methodOrPropName} should not be called during the construction of the custom element for ${getComponentTag(vm)} because the element is not yet in the DOM or has no children yet.`);
1806
+ return renderer.getChildren(vm.elm);
1807
+ },
1808
+ get childNodes() {
1809
+ const vm = getAssociatedVM(this);
1810
+ const renderer = vm.renderer;
1811
+ if (process.env.NODE_ENV !== 'production') {
1812
+ warnIfInvokedDuringConstruction(vm, 'childNodes');
1522
1813
  }
1523
- }
1524
- // @ts-ignore
1525
- LightningElement.prototype = {
1526
- constructor: LightningElement,
1527
- dispatchEvent(event) {
1528
- const vm = getAssociatedVM(this);
1529
- const { elm, renderer: { dispatchEvent }, } = vm;
1530
- return dispatchEvent(elm, event);
1531
- },
1532
- addEventListener(type, listener, options) {
1533
- const vm = getAssociatedVM(this);
1534
- const { elm, renderer: { addEventListener }, } = vm;
1535
- if (process.env.NODE_ENV !== 'production') {
1536
- const vmBeingRendered = getVMBeingRendered();
1537
- shared.assert.invariant(!isInvokingRender, `${vmBeingRendered}.render() method has side effects on the state of ${vm} by adding an event listener for "${type}".`);
1538
- shared.assert.invariant(!isUpdatingTemplate, `Updating the template of ${vmBeingRendered} has side effects on the state of ${vm} by adding an event listener for "${type}".`);
1539
- shared.assert.invariant(shared.isFunction(listener), `Invalid second argument for this.addEventListener() in ${vm} for event "${type}". Expected an EventListener but received ${listener}.`);
1540
- }
1541
- const wrappedListener = getWrappedComponentsListener(vm, listener);
1542
- addEventListener(elm, type, wrappedListener, options);
1543
- },
1544
- removeEventListener(type, listener, options) {
1545
- const vm = getAssociatedVM(this);
1546
- const { elm, renderer: { removeEventListener }, } = vm;
1547
- const wrappedListener = getWrappedComponentsListener(vm, listener);
1548
- removeEventListener(elm, type, wrappedListener, options);
1549
- },
1550
- hasAttribute(name) {
1551
- const vm = getAssociatedVM(this);
1552
- const { elm, renderer: { getAttribute }, } = vm;
1553
- return !shared.isNull(getAttribute(elm, name));
1554
- },
1555
- hasAttributeNS(namespace, name) {
1556
- const vm = getAssociatedVM(this);
1557
- const { elm, renderer: { getAttribute }, } = vm;
1558
- return !shared.isNull(getAttribute(elm, name, namespace));
1559
- },
1560
- removeAttribute(name) {
1561
- const vm = getAssociatedVM(this);
1562
- const { elm, renderer: { removeAttribute }, } = vm;
1563
- unlockAttribute(elm, name);
1564
- removeAttribute(elm, name);
1565
- lockAttribute();
1566
- },
1567
- removeAttributeNS(namespace, name) {
1568
- const { elm, renderer: { removeAttribute }, } = getAssociatedVM(this);
1569
- unlockAttribute(elm, name);
1570
- removeAttribute(elm, name, namespace);
1571
- lockAttribute();
1572
- },
1573
- getAttribute(name) {
1574
- const vm = getAssociatedVM(this);
1575
- const { elm } = vm;
1576
- const { getAttribute } = vm.renderer;
1577
- return getAttribute(elm, name);
1578
- },
1579
- getAttributeNS(namespace, name) {
1580
- const vm = getAssociatedVM(this);
1581
- const { elm } = vm;
1582
- const { getAttribute } = vm.renderer;
1583
- return getAttribute(elm, name, namespace);
1584
- },
1585
- setAttribute(name, value) {
1586
- const vm = getAssociatedVM(this);
1587
- const { elm, renderer: { setAttribute }, } = vm;
1588
- if (process.env.NODE_ENV !== 'production') {
1589
- shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1590
- }
1591
- unlockAttribute(elm, name);
1592
- setAttribute(elm, name, value);
1593
- lockAttribute();
1594
- },
1595
- setAttributeNS(namespace, name, value) {
1596
- const vm = getAssociatedVM(this);
1597
- const { elm, renderer: { setAttribute }, } = vm;
1598
- if (process.env.NODE_ENV !== 'production') {
1599
- shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct '${getComponentTag(vm)}': The result must not have attributes.`);
1600
- }
1601
- unlockAttribute(elm, name);
1602
- setAttribute(elm, name, value, namespace);
1603
- lockAttribute();
1604
- },
1605
- getBoundingClientRect() {
1606
- const vm = getAssociatedVM(this);
1607
- const { elm, renderer: { getBoundingClientRect }, } = vm;
1608
- if (process.env.NODE_ENV !== 'production') {
1609
- warnIfInvokedDuringConstruction(vm, 'getBoundingClientRect()');
1610
- }
1611
- return getBoundingClientRect(elm);
1612
- },
1613
- get isConnected() {
1614
- const vm = getAssociatedVM(this);
1615
- const { elm, renderer: { isConnected }, } = vm;
1616
- return isConnected(elm);
1617
- },
1618
- get classList() {
1619
- const vm = getAssociatedVM(this);
1620
- const { elm, renderer: { getClassList }, } = vm;
1621
- if (process.env.NODE_ENV !== 'production') {
1622
- // TODO [#1290]: this still fails in dev but works in production, eventually, we should
1623
- // just throw in all modes
1624
- shared.assert.isFalse(isBeingConstructed(vm), `Failed to construct ${vm}: The result must not have attributes. Adding or tampering with classname in constructor is not allowed in a web component, use connectedCallback() instead.`);
1625
- }
1626
- return getClassList(elm);
1627
- },
1628
- get template() {
1629
- const vm = getAssociatedVM(this);
1630
- if (process.env.NODE_ENV !== 'production') {
1631
- if (vm.renderMode === 0 /* RenderMode.Light */) {
1632
- logError('`this.template` returns null for light DOM components. Since there is no shadow, the rendered content can be accessed via `this` itself. e.g. instead of `this.template.querySelector`, use `this.querySelector`.');
1633
- }
1634
- }
1635
- return vm.shadowRoot;
1636
- },
1637
- get refs() {
1638
- const vm = getAssociatedVM(this);
1639
- if (isUpdatingTemplate) {
1640
- if (process.env.NODE_ENV !== 'production') {
1641
- logError(`this.refs should not be called while ${getComponentTag(vm)} is rendering. Use this.refs only when the DOM is stable, e.g. in renderedCallback().`);
1642
- }
1643
- // If the template is in the process of being updated, then we don't want to go through the normal
1644
- // process of returning the refs and caching them, because the state of the refs is unstable.
1645
- // This can happen if e.g. a template contains `<div class={foo}></div>` and `foo` is computed
1646
- // based on `this.refs.bar`.
1647
- return;
1648
- }
1649
- if (process.env.NODE_ENV !== 'production') {
1650
- warnIfInvokedDuringConstruction(vm, 'refs');
1651
- }
1652
- const { refVNodes, hasRefVNodes, cmpTemplate } = vm;
1653
- // If the `cmpTemplate` is null, that means that the template has not been rendered yet. Most likely this occurs
1654
- // if `this.refs` is called during the `connectedCallback` phase. The DOM elements have not been rendered yet,
1655
- // so log a warning. Note we also check `isBeingConstructed()` to avoid a double warning (due to
1656
- // `warnIfInvokedDuringConstruction` above).
1657
- if (process.env.NODE_ENV !== 'production' &&
1658
- shared.isNull(cmpTemplate) &&
1659
- !isBeingConstructed(vm)) {
1660
- logError(`this.refs is undefined for ${getComponentTag(vm)}. This is either because the attached template has no "lwc:ref" directive, or this.refs was ` +
1661
- `invoked before renderedCallback(). Use this.refs only when the referenced HTML elements have ` +
1662
- `been rendered to the DOM, such as within renderedCallback() or disconnectedCallback().`);
1663
- }
1664
- // For backwards compatibility with component written before template refs
1665
- // were introduced, we return undefined if the template has no refs defined
1666
- // anywhere. This fixes components that may want to add an expando called `refs`
1667
- // and are checking if it exists with `if (this.refs)` before adding it.
1668
- // Note it is not sufficient to just check if `refVNodes` is null or empty,
1669
- // because a template may have `lwc:ref` defined within a falsy `if:true` block.
1670
- if (!hasRefVNodes) {
1671
- return;
1672
- }
1673
- // For templates that are using `lwc:ref`, if there are no refs currently available
1674
- // (e.g. refs inside of a falsy `if:true` block), we return an empty object.
1675
- if (shared.isNull(refVNodes)) {
1676
- return EMPTY_REFS;
1677
- }
1678
- // The refNodes can be cached based on the refVNodes, since the refVNodes
1679
- // are recreated from scratch every time the template is rendered.
1680
- // This happens with `vm.refVNodes = null` in `template.ts` in `@lwc/engine-core`.
1681
- let refs = refsCache.get(refVNodes);
1682
- if (shared.isUndefined(refs)) {
1683
- refs = shared.create(null);
1684
- for (const key of shared.keys(refVNodes)) {
1685
- refs[key] = refVNodes[key].elm;
1686
- }
1687
- shared.freeze(refs);
1688
- refsCache.set(refVNodes, refs);
1689
- }
1690
- return refs;
1691
- },
1692
- // For backwards compat, we allow component authors to set `refs` as an expando
1693
- set refs(value) {
1694
- shared.defineProperty(this, 'refs', {
1695
- configurable: true,
1696
- enumerable: true,
1697
- writable: true,
1698
- value,
1699
- });
1700
- },
1701
- get shadowRoot() {
1702
- // From within the component instance, the shadowRoot is always reported as "closed".
1703
- // Authors should rely on this.template instead.
1704
- return null;
1705
- },
1706
- get children() {
1707
- const vm = getAssociatedVM(this);
1708
- const renderer = vm.renderer;
1709
- if (process.env.NODE_ENV !== 'production') {
1710
- warnIfInvokedDuringConstruction(vm, 'children');
1711
- }
1712
- return renderer.getChildren(vm.elm);
1713
- },
1714
- get childNodes() {
1715
- const vm = getAssociatedVM(this);
1716
- const renderer = vm.renderer;
1717
- if (process.env.NODE_ENV !== 'production') {
1718
- warnIfInvokedDuringConstruction(vm, 'childNodes');
1719
- }
1720
- return renderer.getChildNodes(vm.elm);
1721
- },
1722
- get firstChild() {
1723
- const vm = getAssociatedVM(this);
1724
- const renderer = vm.renderer;
1725
- if (process.env.NODE_ENV !== 'production') {
1726
- warnIfInvokedDuringConstruction(vm, 'firstChild');
1727
- }
1728
- return renderer.getFirstChild(vm.elm);
1729
- },
1730
- get firstElementChild() {
1731
- const vm = getAssociatedVM(this);
1732
- const renderer = vm.renderer;
1733
- if (process.env.NODE_ENV !== 'production') {
1734
- warnIfInvokedDuringConstruction(vm, 'firstElementChild');
1735
- }
1736
- return renderer.getFirstElementChild(vm.elm);
1737
- },
1738
- get lastChild() {
1739
- const vm = getAssociatedVM(this);
1740
- const renderer = vm.renderer;
1741
- if (process.env.NODE_ENV !== 'production') {
1742
- warnIfInvokedDuringConstruction(vm, 'lastChild');
1743
- }
1744
- return renderer.getLastChild(vm.elm);
1745
- },
1746
- get lastElementChild() {
1747
- const vm = getAssociatedVM(this);
1748
- const renderer = vm.renderer;
1749
- if (process.env.NODE_ENV !== 'production') {
1750
- warnIfInvokedDuringConstruction(vm, 'lastElementChild');
1751
- }
1752
- return renderer.getLastElementChild(vm.elm);
1753
- },
1754
- render() {
1755
- const vm = getAssociatedVM(this);
1756
- return vm.def.template;
1757
- },
1758
- toString() {
1759
- const vm = getAssociatedVM(this);
1760
- return `[object ${vm.def.name}]`;
1761
- },
1814
+ return renderer.getChildNodes(vm.elm);
1815
+ },
1816
+ get firstChild() {
1817
+ const vm = getAssociatedVM(this);
1818
+ const renderer = vm.renderer;
1819
+ if (process.env.NODE_ENV !== 'production') {
1820
+ warnIfInvokedDuringConstruction(vm, 'firstChild');
1821
+ }
1822
+ return renderer.getFirstChild(vm.elm);
1823
+ },
1824
+ get firstElementChild() {
1825
+ const vm = getAssociatedVM(this);
1826
+ const renderer = vm.renderer;
1827
+ if (process.env.NODE_ENV !== 'production') {
1828
+ warnIfInvokedDuringConstruction(vm, 'firstElementChild');
1829
+ }
1830
+ return renderer.getFirstElementChild(vm.elm);
1831
+ },
1832
+ get lastChild() {
1833
+ const vm = getAssociatedVM(this);
1834
+ const renderer = vm.renderer;
1835
+ if (process.env.NODE_ENV !== 'production') {
1836
+ warnIfInvokedDuringConstruction(vm, 'lastChild');
1837
+ }
1838
+ return renderer.getLastChild(vm.elm);
1839
+ },
1840
+ get lastElementChild() {
1841
+ const vm = getAssociatedVM(this);
1842
+ const renderer = vm.renderer;
1843
+ if (process.env.NODE_ENV !== 'production') {
1844
+ warnIfInvokedDuringConstruction(vm, 'lastElementChild');
1845
+ }
1846
+ return renderer.getLastElementChild(vm.elm);
1847
+ },
1848
+ render() {
1849
+ const vm = getAssociatedVM(this);
1850
+ return vm.def.template;
1851
+ },
1852
+ toString() {
1853
+ const vm = getAssociatedVM(this);
1854
+ return `[object ${vm.def.name}]`;
1855
+ }
1762
1856
  };
1763
1857
  const queryAndChildGetterDescriptors = shared.create(null);
1764
- const queryMethods = [
1765
- 'getElementsByClassName',
1766
- 'getElementsByTagName',
1767
- 'querySelector',
1768
- 'querySelectorAll',
1769
- ];
1858
+ const queryMethods = ['getElementsByClassName', 'getElementsByTagName', 'querySelector', 'querySelectorAll'];
1770
1859
  // Generic passthrough for query APIs on HTMLElement to the relevant Renderer APIs
1771
1860
  for (const queryMethod of queryMethods) {
1772
- queryAndChildGetterDescriptors[queryMethod] = {
1773
- value(arg) {
1774
- const vm = getAssociatedVM(this);
1775
- const { elm, renderer } = vm;
1776
- if (process.env.NODE_ENV !== 'production') {
1777
- warnIfInvokedDuringConstruction(vm, `${queryMethod}()`);
1778
- }
1779
- return renderer[queryMethod](elm, arg);
1780
- },
1781
- configurable: true,
1782
- enumerable: true,
1783
- writable: true,
1784
- };
1861
+ queryAndChildGetterDescriptors[queryMethod] = {
1862
+ value(arg) {
1863
+ const vm = getAssociatedVM(this);
1864
+ const {
1865
+ elm,
1866
+ renderer
1867
+ } = vm;
1868
+ if (process.env.NODE_ENV !== 'production') {
1869
+ warnIfInvokedDuringConstruction(vm, `${queryMethod}()`);
1870
+ }
1871
+ return renderer[queryMethod](elm, arg);
1872
+ },
1873
+ configurable: true,
1874
+ enumerable: true,
1875
+ writable: true
1876
+ };
1785
1877
  }
1786
1878
  shared.defineProperties(LightningElement.prototype, queryAndChildGetterDescriptors);
1787
1879
  const lightningBasedDescriptors = shared.create(null);
1788
1880
  for (const propName in HTMLElementOriginalDescriptors) {
1789
- lightningBasedDescriptors[propName] = createBridgeToElementDescriptor(propName, HTMLElementOriginalDescriptors[propName]);
1881
+ lightningBasedDescriptors[propName] = createBridgeToElementDescriptor(propName, HTMLElementOriginalDescriptors[propName]);
1790
1882
  }
1791
1883
  shared.defineProperties(LightningElement.prototype, lightningBasedDescriptors);
1884
+ function applyAriaReflectionToLightningElement() {
1885
+ // If ARIA reflection is not applied globally to Element.prototype, or if we are running server-side,
1886
+ // apply it to LightningElement.prototype.
1887
+ // This allows `this.aria*` property accessors to work from inside a component, and to reflect `aria-*` attrs.
1888
+ ariaReflection.applyAriaReflection(LightningElement.prototype);
1889
+ }
1890
+ // The reason for this odd if/else branching is limitations in @lwc/features:
1891
+ // https://github.com/salesforce/lwc/blob/master/packages/%40lwc/features/README.md#only-works-with-if-statements
1892
+ if (features.lwcRuntimeFlags.DISABLE_ARIA_REFLECTION_POLYFILL) {
1893
+ applyAriaReflectionToLightningElement();
1894
+ } else if (!process.env.IS_BROWSER) {
1895
+ applyAriaReflectionToLightningElement();
1896
+ }
1792
1897
  shared.defineProperty(LightningElement, 'CustomElementConstructor', {
1793
- get() {
1794
- // If required, a runtime-specific implementation must be defined.
1795
- throw new ReferenceError('The current runtime does not support CustomElementConstructor.');
1796
- },
1797
- configurable: true,
1898
+ get() {
1899
+ // If required, a runtime-specific implementation must be defined.
1900
+ throw new ReferenceError('The current runtime does not support CustomElementConstructor.');
1901
+ },
1902
+ configurable: true
1798
1903
  });
1799
1904
  if (process.env.NODE_ENV !== 'production') {
1800
- patchLightningElementPrototypeWithRestrictions(LightningElement.prototype);
1905
+ patchLightningElementPrototypeWithRestrictions(LightningElement.prototype);
1801
1906
  }
1802
1907
 
1803
1908
  function createObservedFieldPropertyDescriptor(key) {
@@ -2257,138 +2362,161 @@ function sanitizeAttribute(tagName, namespaceUri, attrName, attrValue) {
2257
2362
  const cachedGetterByKey = shared.create(null);
2258
2363
  const cachedSetterByKey = shared.create(null);
2259
2364
  function createGetter(key) {
2260
- let fn = cachedGetterByKey[key];
2261
- if (shared.isUndefined(fn)) {
2262
- fn = cachedGetterByKey[key] = function () {
2263
- const vm = getAssociatedVM(this);
2264
- const { getHook } = vm;
2265
- return getHook(vm.component, key);
2266
- };
2267
- }
2268
- return fn;
2365
+ let fn = cachedGetterByKey[key];
2366
+ if (shared.isUndefined(fn)) {
2367
+ fn = cachedGetterByKey[key] = function () {
2368
+ const vm = getAssociatedVM(this);
2369
+ const {
2370
+ getHook
2371
+ } = vm;
2372
+ return getHook(vm.component, key);
2373
+ };
2374
+ }
2375
+ return fn;
2269
2376
  }
2270
2377
  function createSetter(key) {
2271
- let fn = cachedSetterByKey[key];
2272
- if (shared.isUndefined(fn)) {
2273
- fn = cachedSetterByKey[key] = function (newValue) {
2274
- const vm = getAssociatedVM(this);
2275
- const { setHook } = vm;
2276
- newValue = getReadOnlyProxy(newValue);
2277
- setHook(vm.component, key, newValue);
2278
- };
2279
- }
2280
- return fn;
2378
+ let fn = cachedSetterByKey[key];
2379
+ if (shared.isUndefined(fn)) {
2380
+ fn = cachedSetterByKey[key] = function (newValue) {
2381
+ const vm = getAssociatedVM(this);
2382
+ const {
2383
+ setHook
2384
+ } = vm;
2385
+ newValue = getReadOnlyProxy(newValue);
2386
+ setHook(vm.component, key, newValue);
2387
+ };
2388
+ }
2389
+ return fn;
2281
2390
  }
2282
2391
  function createMethodCaller(methodName) {
2283
- return function () {
2284
- const vm = getAssociatedVM(this);
2285
- const { callHook, component } = vm;
2286
- const fn = component[methodName];
2287
- return callHook(vm.component, fn, shared.ArraySlice.call(arguments));
2288
- };
2392
+ return function () {
2393
+ const vm = getAssociatedVM(this);
2394
+ const {
2395
+ callHook,
2396
+ component
2397
+ } = vm;
2398
+ const fn = component[methodName];
2399
+ return callHook(vm.component, fn, shared.ArraySlice.call(arguments));
2400
+ };
2289
2401
  }
2290
2402
  function createAttributeChangedCallback(attributeToPropMap, superAttributeChangedCallback) {
2291
- return function attributeChangedCallback(attrName, oldValue, newValue) {
2292
- if (oldValue === newValue) {
2293
- // Ignore same values.
2294
- return;
2295
- }
2296
- const propName = attributeToPropMap[attrName];
2297
- if (shared.isUndefined(propName)) {
2298
- if (!shared.isUndefined(superAttributeChangedCallback)) {
2299
- // delegate unknown attributes to the super.
2300
- // Typescript does not like it when you treat the `arguments` object as an array
2301
- // @ts-ignore type-mismatch
2302
- superAttributeChangedCallback.apply(this, arguments);
2303
- }
2304
- return;
2305
- }
2306
- if (!isAttributeLocked(this, attrName)) {
2307
- // Ignore changes triggered by the engine itself during:
2308
- // * diffing when public props are attempting to reflect to the DOM
2309
- // * component via `this.setAttribute()`, should never update the prop
2310
- // Both cases, the setAttribute call is always wrapped by the unlocking of the
2311
- // attribute to be changed
2312
- return;
2313
- }
2314
- // Reflect attribute change to the corresponding property when changed from outside.
2315
- this[propName] = newValue;
2316
- };
2317
- }
2318
- function HTMLBridgeElementFactory(SuperClass, props, methods) {
2319
- let HTMLBridgeElement;
2320
- /**
2321
- * Modern browsers will have all Native Constructors as regular Classes
2322
- * and must be instantiated with the new keyword. In older browsers,
2323
- * specifically IE11, those are objects with a prototype property defined,
2324
- * since they are not supposed to be extended or instantiated with the
2325
- * new keyword. This forking logic supports both cases, specifically because
2326
- * wc.ts relies on the construction path of the bridges to create new
2327
- * fully qualifying web components.
2328
- */
2329
- if (shared.isFunction(SuperClass)) {
2330
- HTMLBridgeElement = class extends SuperClass {
2331
- };
2332
- }
2333
- else {
2334
- HTMLBridgeElement = function () {
2335
- // Bridge classes are not supposed to be instantiated directly in
2336
- // browsers that do not support web components.
2337
- throw new TypeError('Illegal constructor');
2338
- };
2339
- // prototype inheritance dance
2340
- shared.setPrototypeOf(HTMLBridgeElement, SuperClass);
2341
- shared.setPrototypeOf(HTMLBridgeElement.prototype, SuperClass.prototype);
2342
- shared.defineProperty(HTMLBridgeElement.prototype, 'constructor', {
2343
- writable: true,
2344
- configurable: true,
2345
- value: HTMLBridgeElement,
2346
- });
2403
+ return function attributeChangedCallback(attrName, oldValue, newValue) {
2404
+ if (oldValue === newValue) {
2405
+ // Ignore same values.
2406
+ return;
2347
2407
  }
2348
- // generating the hash table for attributes to avoid duplicate fields and facilitate validation
2349
- // and false positives in case of inheritance.
2350
- const attributeToPropMap = shared.create(null);
2351
- const { attributeChangedCallback: superAttributeChangedCallback } = SuperClass.prototype;
2352
- const { observedAttributes: superObservedAttributes = [] } = SuperClass;
2353
- const descriptors = shared.create(null);
2354
- // expose getters and setters for each public props on the new Element Bridge
2355
- for (let i = 0, len = props.length; i < len; i += 1) {
2356
- const propName = props[i];
2357
- attributeToPropMap[shared.htmlPropertyToAttribute(propName)] = propName;
2358
- descriptors[propName] = {
2359
- get: createGetter(propName),
2360
- set: createSetter(propName),
2361
- enumerable: true,
2362
- configurable: true,
2363
- };
2408
+ const propName = attributeToPropMap[attrName];
2409
+ if (shared.isUndefined(propName)) {
2410
+ if (!shared.isUndefined(superAttributeChangedCallback)) {
2411
+ // delegate unknown attributes to the super.
2412
+ // Typescript does not like it when you treat the `arguments` object as an array
2413
+ // @ts-ignore type-mismatch
2414
+ superAttributeChangedCallback.apply(this, arguments);
2415
+ }
2416
+ return;
2364
2417
  }
2365
- // expose public methods as props on the new Element Bridge
2366
- for (let i = 0, len = methods.length; i < len; i += 1) {
2367
- const methodName = methods[i];
2368
- descriptors[methodName] = {
2369
- value: createMethodCaller(methodName),
2370
- writable: true,
2371
- configurable: true,
2372
- };
2418
+ if (!isAttributeLocked(this, attrName)) {
2419
+ // Ignore changes triggered by the engine itself during:
2420
+ // * diffing when public props are attempting to reflect to the DOM
2421
+ // * component via `this.setAttribute()`, should never update the prop
2422
+ // Both cases, the setAttribute call is always wrapped by the unlocking of the
2423
+ // attribute to be changed
2424
+ return;
2373
2425
  }
2374
- // creating a new attributeChangedCallback per bridge because they are bound to the corresponding
2375
- // map of attributes to props. We do this after all other props and methods to avoid the possibility
2376
- // of getting overrule by a class declaration in user-land, and we make it non-writable, non-configurable
2377
- // to preserve this definition.
2378
- descriptors.attributeChangedCallback = {
2379
- value: createAttributeChangedCallback(attributeToPropMap, superAttributeChangedCallback),
2426
+ // Reflect attribute change to the corresponding property when changed from outside.
2427
+ this[propName] = newValue;
2428
+ };
2429
+ }
2430
+ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2431
+ let HTMLBridgeElement;
2432
+ /**
2433
+ * Modern browsers will have all Native Constructors as regular Classes
2434
+ * and must be instantiated with the new keyword. In older browsers,
2435
+ * specifically IE11, those are objects with a prototype property defined,
2436
+ * since they are not supposed to be extended or instantiated with the
2437
+ * new keyword. This forking logic supports both cases, specifically because
2438
+ * wc.ts relies on the construction path of the bridges to create new
2439
+ * fully qualifying web components.
2440
+ */
2441
+ if (shared.isFunction(SuperClass)) {
2442
+ HTMLBridgeElement = class extends SuperClass {};
2443
+ } else {
2444
+ HTMLBridgeElement = function () {
2445
+ // Bridge classes are not supposed to be instantiated directly in
2446
+ // browsers that do not support web components.
2447
+ throw new TypeError('Illegal constructor');
2380
2448
  };
2381
- // Specify attributes for which we want to reflect changes back to their corresponding
2382
- // properties via attributeChangedCallback.
2383
- shared.defineProperty(HTMLBridgeElement, 'observedAttributes', {
2384
- get() {
2385
- return [...superObservedAttributes, ...shared.keys(attributeToPropMap)];
2386
- },
2449
+ // prototype inheritance dance
2450
+ shared.setPrototypeOf(HTMLBridgeElement, SuperClass);
2451
+ shared.setPrototypeOf(HTMLBridgeElement.prototype, SuperClass.prototype);
2452
+ shared.defineProperty(HTMLBridgeElement.prototype, 'constructor', {
2453
+ writable: true,
2454
+ configurable: true,
2455
+ value: HTMLBridgeElement
2387
2456
  });
2388
- shared.defineProperties(HTMLBridgeElement.prototype, descriptors);
2389
- return HTMLBridgeElement;
2457
+ }
2458
+ // generating the hash table for attributes to avoid duplicate fields and facilitate validation
2459
+ // and false positives in case of inheritance.
2460
+ const attributeToPropMap = shared.create(null);
2461
+ const {
2462
+ attributeChangedCallback: superAttributeChangedCallback
2463
+ } = SuperClass.prototype;
2464
+ const {
2465
+ observedAttributes: superObservedAttributes = []
2466
+ } = SuperClass;
2467
+ const descriptors = shared.create(null);
2468
+ // expose getters and setters for each public props on the new Element Bridge
2469
+ for (let i = 0, len = props.length; i < len; i += 1) {
2470
+ const propName = props[i];
2471
+ attributeToPropMap[shared.htmlPropertyToAttribute(propName)] = propName;
2472
+ descriptors[propName] = {
2473
+ get: createGetter(propName),
2474
+ set: createSetter(propName),
2475
+ enumerable: true,
2476
+ configurable: true
2477
+ };
2478
+ }
2479
+ // expose public methods as props on the new Element Bridge
2480
+ for (let i = 0, len = methods.length; i < len; i += 1) {
2481
+ const methodName = methods[i];
2482
+ descriptors[methodName] = {
2483
+ value: createMethodCaller(methodName),
2484
+ writable: true,
2485
+ configurable: true
2486
+ };
2487
+ }
2488
+ // creating a new attributeChangedCallback per bridge because they are bound to the corresponding
2489
+ // map of attributes to props. We do this after all other props and methods to avoid the possibility
2490
+ // of getting overrule by a class declaration in user-land, and we make it non-writable, non-configurable
2491
+ // to preserve this definition.
2492
+ descriptors.attributeChangedCallback = {
2493
+ value: createAttributeChangedCallback(attributeToPropMap, superAttributeChangedCallback)
2494
+ };
2495
+ // Specify attributes for which we want to reflect changes back to their corresponding
2496
+ // properties via attributeChangedCallback.
2497
+ shared.defineProperty(HTMLBridgeElement, 'observedAttributes', {
2498
+ get() {
2499
+ return [...superObservedAttributes, ...shared.keys(attributeToPropMap)];
2500
+ }
2501
+ });
2502
+ shared.defineProperties(HTMLBridgeElement.prototype, descriptors);
2503
+ return HTMLBridgeElement;
2390
2504
  }
2391
2505
  const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, shared.getOwnPropertyNames(HTMLElementOriginalDescriptors), []);
2506
+ if (process.env.IS_BROWSER) {
2507
+ // This ARIA reflection only really makes sense in the browser. On the server, there is no `renderedCallback()`,
2508
+ // so you cannot do e.g. `this.template.querySelector('x-child').ariaBusy = 'true'`. So we don't need to expose
2509
+ // ARIA props outside the LightningElement
2510
+ if (features.lwcRuntimeFlags.DISABLE_ARIA_REFLECTION_POLYFILL) {
2511
+ // If ARIA reflection is not applied globally to Element.prototype, apply it to HTMLBridgeElement.prototype.
2512
+ // This allows `elm.aria*` property accessors to work from outside a component, and to reflect `aria-*` attrs.
2513
+ // This is especially important because the template compiler compiles aria-* attrs on components to aria* props
2514
+ //
2515
+ // Also note that we apply this to BaseBridgeElement.prototype to avoid excessively redefining property
2516
+ // accessors inside the HTMLBridgeElementFactory.
2517
+ ariaReflection.applyAriaReflection(BaseBridgeElement.prototype);
2518
+ }
2519
+ }
2392
2520
  shared.freeze(BaseBridgeElement);
2393
2521
  shared.seal(BaseBridgeElement.prototype);
2394
2522
 
@@ -6533,4 +6661,4 @@ exports.swapTemplate = swapTemplate;
6533
6661
  exports.track = track;
6534
6662
  exports.unwrap = unwrap;
6535
6663
  exports.wire = wire;
6536
- /* version: 2.32.1 */
6664
+ /* version: 2.33.0 */