diff --git a/packages/@lwc/engine/src/framework/__tests__/vm.spec.ts b/packages/@lwc/engine/src/framework/__tests__/vm.spec.ts
index e6a886d843..0898a0f9fc 100644
--- a/packages/@lwc/engine/src/framework/__tests__/vm.spec.ts
+++ b/packages/@lwc/engine/src/framework/__tests__/vm.spec.ts
@@ -8,6 +8,7 @@ import { compileTemplate } from 'test-utils';
import { createElement, LightningElement, registerDecorators } from '../main';
import { ViewModelReflection } from '../utils';
import { getComponentVM } from '../vm';
+import { getHiddenField } from '../../shared/fields';
const emptyTemplate = compileTemplate(``);
@@ -16,24 +17,26 @@ describe('vm', () => {
it('should have idx>0 (creation index) during construction', () => {
class MyComponent1 extends LightningElement {}
const elm = createElement('x-foo', { is: MyComponent1 });
- expect(elm[ViewModelReflection].idx).toBeGreaterThan(0);
+ const hiddenFields = getHiddenField(elm, ViewModelReflection);
+ expect(hiddenFields.idx).toBeGreaterThan(0);
});
it('should have idx>0 after insertion', () => {
class MyComponent2 extends LightningElement {}
const elm = createElement('x-foo', { is: MyComponent2 });
document.body.appendChild(elm);
- expect(elm[ViewModelReflection].idx).toBeGreaterThan(0);
+ const hiddenFields = getHiddenField(elm, ViewModelReflection);
+ expect(hiddenFields.idx).toBeGreaterThan(0);
});
it('should preserve insertion index after removal of root', () => {
class MyComponent3 extends LightningElement {}
const elm = createElement('x-foo', { is: MyComponent3 });
document.body.appendChild(elm);
- const idx = elm[ViewModelReflection].idx;
- expect(idx).toBeGreaterThan(0);
+ const hiddenFields = getHiddenField(elm, ViewModelReflection);
+ expect(hiddenFields.idx).toBeGreaterThan(0);
document.body.removeChild(elm);
- expect(elm[ViewModelReflection].idx).toBe(idx);
+ expect(hiddenFields.idx).toBeGreaterThan(0);
});
it('should assign bigger idx to children', () => {
diff --git a/packages/@lwc/engine/src/framework/base-lightning-element.ts b/packages/@lwc/engine/src/framework/base-lightning-element.ts
index 7d782ef2f4..22c7067014 100644
--- a/packages/@lwc/engine/src/framework/base-lightning-element.ts
+++ b/packages/@lwc/engine/src/framework/base-lightning-element.ts
@@ -34,7 +34,7 @@ import {
getComponentAsString,
getTemplateReactiveObserver,
} from './component';
-import { setInternalField, setHiddenField } from '../shared/fields';
+import { setHiddenField } from '../shared/fields';
import { ViewModelReflection, EmptyObject } from './utils';
import { vmBeingConstructed, isBeingConstructed, isRendering, vmBeingRendered } from './invoker';
import { getComponentVM, VM } from './vm';
@@ -282,8 +282,8 @@ function BaseLightningElementConstructor(this: LightningElement) {
const cmpRoot = elm.attachShadow(shadowRootOptions);
// linking elm, shadow root and component with the VM
setHiddenField(component, ViewModelReflection, vm);
- setInternalField(elm, ViewModelReflection, vm);
- setInternalField(cmpRoot, ViewModelReflection, vm);
+ setHiddenField(cmpRoot, ViewModelReflection, vm);
+ setHiddenField(elm, ViewModelReflection, vm);
// VM is now initialized
(vm as VM).cmpRoot = cmpRoot;
if (process.env.NODE_ENV !== 'production') {
diff --git a/packages/@lwc/engine/src/framework/def.ts b/packages/@lwc/engine/src/framework/def.ts
index 735c3c4252..431fcd7126 100644
--- a/packages/@lwc/engine/src/framework/def.ts
+++ b/packages/@lwc/engine/src/framework/def.ts
@@ -26,7 +26,6 @@ import {
defineProperties,
} from '../shared/language';
import { createObservedFieldsDescriptorMap } from './observed-fields';
-import { getInternalField } from '../shared/fields';
import {
resolveCircularModuleDependency,
isCircularModuleDependency,
@@ -228,7 +227,7 @@ export function getComponentDef(Ctor: any, subclassComponentName?: string): Comp
export function getComponentConstructor(elm: HTMLElement): ComponentConstructor | null {
let ctor: ComponentConstructor | null = null;
if (elm instanceof HTMLElement) {
- const vm = getInternalField(elm, ViewModelReflection);
+ const vm = getHiddenField(elm, ViewModelReflection);
if (!isUndefined(vm)) {
ctor = vm.def.ctor;
}
@@ -251,6 +250,7 @@ import {
} from './base-bridge-element';
import { getDecoratorsMeta } from './decorators/register';
import { defaultEmptyTemplate } from './secure-template';
+import { getHiddenField } from '../shared/fields';
const lightingElementDef: ComponentDef = {
ctor: BaseLightningElement,
diff --git a/packages/@lwc/engine/src/framework/hooks.ts b/packages/@lwc/engine/src/framework/hooks.ts
index 5b6c38d9d7..26f5e71349 100644
--- a/packages/@lwc/engine/src/framework/hooks.ts
+++ b/packages/@lwc/engine/src/framework/hooks.ts
@@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import assert from '../shared/assert';
-import { isArray, isUndefined, isTrue, hasOwnProperty, isNull } from '../shared/language';
+import { isArray, isUndefined, isTrue, isNull } from '../shared/language';
import { EmptyArray, ViewModelReflection, EmptyObject, useSyntheticShadow } from './utils';
import {
rerenderVM,
@@ -33,6 +33,7 @@ import {
lockDomMutation,
} from './restrictions';
import { getComponentDef, setElementProto } from './def';
+import { getHiddenField } from '../shared/fields';
const noop = () => void 0;
@@ -174,7 +175,7 @@ export function allocateChildrenHook(vnode: VCustomElement) {
export function createViewModelHook(vnode: VCustomElement) {
const elm = vnode.elm as HTMLElement;
- if (hasOwnProperty.call(elm, ViewModelReflection)) {
+ if (!isUndefined(getHiddenField(elm, ViewModelReflection))) {
// There is a possibility that a custom element is registered under tagName,
// in which case, the initialization is already carry on, and there is nothing else
// to do here since this hook is called right after invoking `document.createElement`.
diff --git a/packages/@lwc/engine/src/framework/modules/context.ts b/packages/@lwc/engine/src/framework/modules/context.ts
index eaede0cd1a..78e0f24061 100644
--- a/packages/@lwc/engine/src/framework/modules/context.ts
+++ b/packages/@lwc/engine/src/framework/modules/context.ts
@@ -7,7 +7,7 @@
import { isUndefined, assign } from '../../shared/language';
import { VNode } from '../../3rdparty/snabbdom/types';
import { ViewModelReflection } from '../utils';
-import { getInternalField } from '../../shared/fields';
+import { getHiddenField } from '../../shared/fields';
import { VM } from '../vm';
function createContext(vnode: VNode) {
@@ -20,7 +20,7 @@ function createContext(vnode: VNode) {
}
const elm = vnode.elm as Element;
- const vm: VM = getInternalField(elm, ViewModelReflection);
+ const vm: VM = getHiddenField(elm, ViewModelReflection);
if (!isUndefined(vm)) {
assign(vm.context, context);
diff --git a/packages/@lwc/engine/src/framework/modules/props.ts b/packages/@lwc/engine/src/framework/modules/props.ts
index cab98fbbb4..daea62710d 100644
--- a/packages/@lwc/engine/src/framework/modules/props.ts
+++ b/packages/@lwc/engine/src/framework/modules/props.ts
@@ -6,7 +6,7 @@
*/
import assert from '../../shared/assert';
import { isUndefined, keys } from '../../shared/language';
-import { getInternalField } from '../../shared/fields';
+import { getHiddenField } from '../../shared/fields';
import { ViewModelReflection } from '../utils';
import { prepareForPropUpdate } from '../base-bridge-element';
import { VNode } from '../../3rdparty/snabbdom/types';
@@ -36,7 +36,7 @@ function update(oldVnode: VNode, vnode: VNode) {
}
const elm = vnode.elm as Element;
- const vm = getInternalField(elm, ViewModelReflection);
+ const vm = getHiddenField(elm, ViewModelReflection);
const isFirstPatch = isUndefined(oldProps);
const isCustomElement = !isUndefined(vm);
const { sel } = vnode;
diff --git a/packages/@lwc/engine/src/framework/upgrade.ts b/packages/@lwc/engine/src/framework/upgrade.ts
index 7ab84080ac..3297a42375 100644
--- a/packages/@lwc/engine/src/framework/upgrade.ts
+++ b/packages/@lwc/engine/src/framework/upgrade.ts
@@ -14,7 +14,7 @@ import {
resolveCircularModuleDependency,
ViewModelReflection,
} from './utils';
-import { setInternalField, getInternalField, createFieldName } from '../shared/fields';
+import { setHiddenField, getHiddenField, createFieldName } from '../shared/fields';
import { getComponentDef, setElementProto } from './def';
import { patchCustomElementWithRestrictions } from './restrictions';
import { GlobalMeasurementPhase, startGlobalMeasure, endGlobalMeasure } from './performance-timing';
@@ -27,7 +27,7 @@ function callNodeSlot(node: Node, slot: symbol): Node {
if (process.env.NODE_ENV !== 'production') {
assert.isTrue(node, `callNodeSlot() should not be called for a non-object`);
}
- const fn = getInternalField(node, slot);
+ const fn = getHiddenField(node, slot);
if (!isUndefined(fn)) {
fn();
}
@@ -97,7 +97,7 @@ export function createElement(sel: string, options: CreateElementOptions): HTMLE
// Create element with correct tagName
const element = document.createElement(sel);
- if (!isUndefined(getInternalField(element, ViewModelReflection))) {
+ if (!isUndefined(getHiddenField(element, ViewModelReflection))) {
// There is a possibility that a custom element is registered under tagName,
// in which case, the initialization is already carry on, and there is nothing else
// to do here.
@@ -117,7 +117,7 @@ export function createElement(sel: string, options: CreateElementOptions): HTMLE
// In case the element is not initialized already, we need to carry on the manual creation
createVM(element, Ctor, { mode, isRoot: true, owner: null });
// Handle insertion and removal from the DOM manually
- setInternalField(element, ConnectingSlot, () => {
+ setHiddenField(element, ConnectingSlot, () => {
const vm = getCustomElementVM(element);
startGlobalMeasure(GlobalMeasurementPhase.HYDRATE, vm);
if (vm.state === VMState.connected) {
@@ -127,7 +127,7 @@ export function createElement(sel: string, options: CreateElementOptions): HTMLE
appendRootVM(vm);
endGlobalMeasure(GlobalMeasurementPhase.HYDRATE, vm);
});
- setInternalField(element, DisconnectingSlot, () => {
+ setHiddenField(element, DisconnectingSlot, () => {
const vm = getCustomElementVM(element);
removeRootVM(vm);
});
diff --git a/packages/@lwc/engine/src/framework/vm.ts b/packages/@lwc/engine/src/framework/vm.ts
index d91738a2d2..e912d8414e 100644
--- a/packages/@lwc/engine/src/framework/vm.ts
+++ b/packages/@lwc/engine/src/framework/vm.ts
@@ -27,7 +27,7 @@ import {
isFalse,
isArray,
} from '../shared/language';
-import { getInternalField, getHiddenField } from '../shared/fields';
+import { getHiddenField } from '../shared/fields';
import {
ViewModelReflection,
addCallbackToNextTick,
@@ -541,7 +541,7 @@ function getErrorBoundaryVM(startingElement: Element | null): VM | undefined {
let vm: VM | undefined;
while (!isNull(elm)) {
- vm = getInternalField(elm, ViewModelReflection);
+ vm = getHiddenField(elm, ViewModelReflection);
if (!isUndefined(vm) && !isUndefined(vm.def.errorCallback)) {
return vm;
}
@@ -560,7 +560,7 @@ export function getErrorComponentStack(startingElement: Element): string {
const wcStack: string[] = [];
let elm: Element | null = startingElement;
do {
- const currentVm: VM | undefined = getInternalField(elm, ViewModelReflection);
+ const currentVm: VM | undefined = getHiddenField(elm, ViewModelReflection);
if (!isUndefined(currentVm)) {
const tagName = tagNameGetter.call(elm);
const is = elm.getAttribute('is');
@@ -626,10 +626,10 @@ export function isNodeFromTemplate(node: Node): boolean {
export function getCustomElementVM(elm: HTMLElement): VM {
if (process.env.NODE_ENV !== 'production') {
- const vm = getInternalField(elm, ViewModelReflection);
+ const vm = getHiddenField(elm, ViewModelReflection);
assert.isTrue(vm && 'cmpRoot' in vm, `${vm} is not a vm.`);
}
- return getInternalField(elm, ViewModelReflection) as VM;
+ return getHiddenField(elm, ViewModelReflection) as VM;
}
export function getComponentVM(component: ComponentInterface): VM {
@@ -643,10 +643,10 @@ export function getComponentVM(component: ComponentInterface): VM {
export function getShadowRootVM(root: ShadowRoot): VM {
// TODO: #1299 - use a weak map instead of an internal field
if (process.env.NODE_ENV !== 'production') {
- const vm = getInternalField(root, ViewModelReflection);
+ const vm = getHiddenField(root, ViewModelReflection);
assert.isTrue(vm && 'cmpRoot' in vm, `${vm} is not a vm.`);
}
- return getInternalField(root, ViewModelReflection) as VM;
+ return getHiddenField(root, ViewModelReflection) as VM;
}
// slow path routine
diff --git a/packages/@lwc/engine/src/shared/fields.ts b/packages/@lwc/engine/src/shared/fields.ts
index c95785d72d..c4985d033b 100644
--- a/packages/@lwc/engine/src/shared/fields.ts
+++ b/packages/@lwc/engine/src/shared/fields.ts
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
-import { defineProperty, create, isUndefined } from './language';
+import { create, isUndefined } from './language';
/**
* In IE11, symbols are expensive.
@@ -16,48 +16,23 @@ const hasNativeSymbolsSupport = Symbol('x').toString() === 'Symbol(x)';
export function createFieldName(key: string): symbol {
// @ts-ignore: using a string as a symbol for perf reasons
- return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-${key}$$`;
+ return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-engine-${key}$$`;
}
-export function setInternalField(o: object, fieldName: symbol, value: any) {
- // TODO: #1299 - use a weak map instead
- defineProperty(o, fieldName, {
- value,
- });
-}
+const hiddenFieldsMap: WeakMap> = new WeakMap();
-export function getInternalField(o: object, fieldName: symbol): any {
- return o[fieldName];
+export function setHiddenField(o: any, fieldName: symbol, value: any) {
+ let valuesByField = hiddenFieldsMap.get(o);
+ if (isUndefined(valuesByField)) {
+ valuesByField = create(null) as (Record);
+ hiddenFieldsMap.set(o, valuesByField);
+ }
+ valuesByField[fieldName] = value;
}
-/**
- * Store fields that should be hidden from outside world
- * hiddenFieldsMap is a WeakMap.
- * It stores a hash of any given objects associative relationships.
- * The hash uses the fieldName as the key, the value represents the other end of the association.
- *
- * For example, if the association is
- * ViewModel
- * Component-A --------------> VM-1
- * then,
- * hiddenFieldsMap : (Component-A, { Symbol(ViewModel) : VM-1 })
- *
- */
-const hiddenFieldsMap: WeakMap> = new WeakMap();
-export const setHiddenField = hasNativeSymbolsSupport
- ? (o: any, fieldName: symbol, value: any): void => {
- let valuesByField = hiddenFieldsMap.get(o);
- if (isUndefined(valuesByField)) {
- valuesByField = create(null) as (Record);
- hiddenFieldsMap.set(o, valuesByField);
- }
- valuesByField[fieldName] = value;
- }
- : setInternalField; // Fall back to symbol based approach in compat mode
-
-export const getHiddenField = hasNativeSymbolsSupport
- ? (o: any, fieldName: symbol): any => {
- const valuesByField = hiddenFieldsMap.get(o);
- return !isUndefined(valuesByField) && valuesByField[fieldName];
- }
- : getInternalField; // Fall back to symbol based approach in compat mode
+export function getHiddenField(o: any, fieldName: symbol) {
+ const valuesByField = hiddenFieldsMap.get(o);
+ if (!isUndefined(valuesByField)) {
+ return valuesByField[fieldName];
+ }
+}
diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/focus.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/focus.ts
index 364139e4de..32a4a1acfc 100644
--- a/packages/@lwc/synthetic-shadow/src/faux-shadow/focus.ts
+++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/focus.ts
@@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import assert from '../shared/assert';
-import { createFieldName, getInternalField, setInternalField } from '../shared/fields';
+import { createFieldName, getHiddenField, setHiddenField } from '../shared/fields';
import { windowAddEventListener, windowRemoveEventListener } from '../env/window';
import {
matches,
@@ -320,8 +320,8 @@ export function ignoreFocus(elm: HTMLElement) {
function bindDocumentMousedownMouseupHandlers(elm: Node) {
const ownerDocument = getOwnerDocument(elm);
- if (!getInternalField(ownerDocument, DidAddMouseDownListener)) {
- setInternalField(ownerDocument, DidAddMouseDownListener, true);
+ if (!getHiddenField(ownerDocument, DidAddMouseDownListener)) {
+ setHiddenField(ownerDocument, DidAddMouseDownListener, true);
addEventListener.call(
ownerDocument,
'mousedown',
diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts
index b33d7f8cbd..629feed204 100644
--- a/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts
+++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts
@@ -408,7 +408,6 @@ defineProperties(Node.prototype, {
},
cloneNode: {
value(this: Node, deep?: boolean): Node {
- deep = isUndefined(deep) || deep;
if (isNodeShadowed(this) || isHostElement(this)) {
return cloneNodePatched.call(this, deep);
}
diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/shadow-root.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/shadow-root.ts
index c0dfbcf3ca..2ae82c1d71 100644
--- a/packages/@lwc/synthetic-shadow/src/faux-shadow/shadow-root.ts
+++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/shadow-root.ts
@@ -23,7 +23,7 @@ import {
isNodeOwnedBy,
isSlotElement,
} from './traverse';
-import { getInternalField, setInternalField, createFieldName } from '../shared/fields';
+import { getHiddenField, setHiddenField, createFieldName } from '../shared/fields';
import { getTextContent } from '../3rdparty/polymer/text-content';
import { createStaticNodeList } from '../shared/static-node-list';
import { DocumentPrototypeActiveElement, elementFromPoint, createComment } from '../env/document';
@@ -59,7 +59,7 @@ interface ShadowRootRecord {
}
function getInternalSlot(root: SyntheticShadowRootInterface | Element): ShadowRootRecord {
- const record: ShadowRootRecord | undefined = getInternalField(root, InternalSlot);
+ const record: ShadowRootRecord | undefined = getHiddenField(root, InternalSlot);
if (isUndefined(record)) {
throw new TypeError();
}
@@ -109,13 +109,13 @@ export function getShadowRoot(elm: Element): SyntheticShadowRootInterface {
// since this check is harmless for nodes as well, and it speeds up things
// to avoid casting before calling this method in few places.
export function isHostElement(elm: Element | Node): boolean {
- return !isUndefined(getInternalField(elm, InternalSlot));
+ return !isUndefined(getHiddenField(elm, InternalSlot));
}
let uid = 0;
export function attachShadow(elm: Element, options: ShadowRootInit): SyntheticShadowRootInterface {
- if (!isUndefined(getInternalField(elm, InternalSlot))) {
+ if (!isUndefined(getHiddenField(elm, InternalSlot))) {
throw new Error(
`Failed to execute 'attachShadow' on 'Element': Shadow root cannot be created on a host which already hosts a shadow tree.`
);
@@ -131,8 +131,8 @@ export function attachShadow(elm: Element, options: ShadowRootInit): SyntheticSh
host: elm,
shadowRoot: sr,
};
- setInternalField(sr, InternalSlot, record);
- setInternalField(elm, InternalSlot, record);
+ setHiddenField(sr, InternalSlot, record);
+ setHiddenField(elm, InternalSlot, record);
const shadowResolver = () => sr;
const x = (shadowResolver.nodeKey = uid++);
setNodeKey(elm, x);
diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/slot.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/slot.ts
index 91c982c706..c14d887e64 100644
--- a/packages/@lwc/synthetic-shadow/src/faux-shadow/slot.ts
+++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/slot.ts
@@ -6,7 +6,7 @@
*/
import assert from '../shared/assert';
import { getAttribute, childrenGetter, setAttribute } from '../env/element';
-import { createFieldName, getInternalField, setInternalField } from '../shared/fields';
+import { createFieldName, getHiddenField, setHiddenField } from '../shared/fields';
import { dispatchEvent } from '../env/dom';
import {
ArrayIndexOf,
@@ -113,9 +113,9 @@ defineProperties(HTMLSlotElement.prototype, {
if (
isNodeShadowed(this) &&
type === 'slotchange' &&
- !getInternalField(this, SlotChangeKey)
+ !getHiddenField(this, SlotChangeKey)
) {
- setInternalField(this, SlotChangeKey, true);
+ setHiddenField(this, SlotChangeKey, true);
if (!observer) {
observer = initSlotObserver();
}
diff --git a/packages/@lwc/synthetic-shadow/src/shared/fields.ts b/packages/@lwc/synthetic-shadow/src/shared/fields.ts
index 1b353fb918..94720e7442 100644
--- a/packages/@lwc/synthetic-shadow/src/shared/fields.ts
+++ b/packages/@lwc/synthetic-shadow/src/shared/fields.ts
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
-import { defineProperty } from './language';
+import { create, isUndefined } from './language';
/**
* In IE11, symbols are expensive.
@@ -16,16 +16,23 @@ const hasNativeSymbolsSupport = Symbol('x').toString() === 'Symbol(x)';
export function createFieldName(key: string): symbol {
// @ts-ignore: using a string as a symbol for perf reasons
- return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-${key}$$`;
+ return hasNativeSymbolsSupport ? Symbol(key) : `$$lwc-synthetic-shadow-${key}$$`;
}
-export function setInternalField(o: object, fieldName: symbol, value: any) {
- // TODO: #1299 - improve this to use a WeakMap
- defineProperty(o, fieldName, {
- value,
- });
+const hiddenFieldsMap: WeakMap> = new WeakMap();
+
+export function setHiddenField(o: any, fieldName: symbol, value: any) {
+ let valuesByField = hiddenFieldsMap.get(o);
+ if (isUndefined(valuesByField)) {
+ valuesByField = create(null) as (Record);
+ hiddenFieldsMap.set(o, valuesByField);
+ }
+ valuesByField[fieldName] = value;
}
-export function getInternalField(o: object, fieldName: symbol): any {
- return o[fieldName];
+export function getHiddenField(o: any, fieldName: symbol) {
+ const valuesByField = hiddenFieldsMap.get(o);
+ if (!isUndefined(valuesByField)) {
+ return valuesByField[fieldName];
+ }
}
diff --git a/packages/@lwc/synthetic-shadow/src/shared/static-html-collection.ts b/packages/@lwc/synthetic-shadow/src/shared/static-html-collection.ts
index 40a06ccb3e..abc47f48be 100644
--- a/packages/@lwc/synthetic-shadow/src/shared/static-html-collection.ts
+++ b/packages/@lwc/synthetic-shadow/src/shared/static-html-collection.ts
@@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { defineProperty, forEach, ArrayMap, create, setPrototypeOf } from './language';
-import { createFieldName, getInternalField, setInternalField } from './fields';
+import { createFieldName, getHiddenField, setHiddenField } from './fields';
const Items = createFieldName('items');
@@ -38,7 +38,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
enumerable: true,
configurable: true,
get() {
- return getInternalField(this, Items).length;
+ return getHiddenField(this, Items).length;
},
},
// https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem-key
@@ -50,7 +50,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
if (isValidHTMLCollectionName(name) && this[name]) {
return this[name];
}
- const items = getInternalField(this, Items);
+ const items = getHiddenField(this, Items);
// Note: loop in reverse so that the first named item matches the named property
for (let len = items.length - 1; len >= 0; len -= 1) {
const item = items[len];
@@ -70,7 +70,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
enumerable: true,
configurable: true,
value(cb, thisArg) {
- forEach.call(getInternalField(this, Items), cb, thisArg);
+ forEach.call(getHiddenField(this, Items), cb, thisArg);
},
},
entries: {
@@ -78,7 +78,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
enumerable: true,
configurable: true,
value() {
- return ArrayMap.call(getInternalField(this, Items), (v: any, i: number) => [i, v]);
+ return ArrayMap.call(getHiddenField(this, Items), (v: any, i: number) => [i, v]);
},
},
keys: {
@@ -86,7 +86,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
enumerable: true,
configurable: true,
value() {
- return ArrayMap.call(getInternalField(this, Items), (v: any, i: number) => i);
+ return ArrayMap.call(getHiddenField(this, Items), (v: any, i: number) => i);
},
},
values: {
@@ -94,7 +94,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
enumerable: true,
configurable: true,
value() {
- return getInternalField(this, Items);
+ return getHiddenField(this, Items);
},
},
[Symbol.iterator]: {
@@ -104,7 +104,7 @@ StaticHTMLCollection.prototype = create(HTMLCollection.prototype, {
let nextIndex = 0;
return {
next: () => {
- const items = getInternalField(this, Items);
+ const items = getHiddenField(this, Items);
return nextIndex < items.length
? {
value: items[nextIndex++],
@@ -138,7 +138,7 @@ setPrototypeOf(StaticHTMLCollection, HTMLCollection);
export function createStaticHTMLCollection(items: T[]): HTMLCollectionOf {
const collection: HTMLCollectionOf = create(StaticHTMLCollection.prototype);
- setInternalField(collection, Items, items);
+ setHiddenField(collection, Items, items);
// setting static indexes
forEach.call(items, (item: T, index: number) => {
defineProperty(collection, index, {
diff --git a/packages/@lwc/synthetic-shadow/src/shared/static-node-list.ts b/packages/@lwc/synthetic-shadow/src/shared/static-node-list.ts
index c69faac4da..bfa92ca5fe 100644
--- a/packages/@lwc/synthetic-shadow/src/shared/static-node-list.ts
+++ b/packages/@lwc/synthetic-shadow/src/shared/static-node-list.ts
@@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { defineProperty, forEach, ArrayMap, create, setPrototypeOf } from './language';
-import { createFieldName, getInternalField, setInternalField } from './fields';
+import { createFieldName, getHiddenField, setHiddenField } from './fields';
const Items = createFieldName('items');
@@ -31,7 +31,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
enumerable: true,
configurable: true,
get() {
- return getInternalField(this, Items).length;
+ return getHiddenField(this, Items).length;
},
},
@@ -42,7 +42,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
enumerable: true,
configurable: true,
value(cb, thisArg) {
- forEach.call(getInternalField(this, Items), cb, thisArg);
+ forEach.call(getHiddenField(this, Items), cb, thisArg);
},
},
entries: {
@@ -50,7 +50,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
enumerable: true,
configurable: true,
value() {
- return ArrayMap.call(getInternalField(this, Items), (v: any, i: number) => [i, v]);
+ return ArrayMap.call(getHiddenField(this, Items), (v: any, i: number) => [i, v]);
},
},
keys: {
@@ -58,7 +58,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
enumerable: true,
configurable: true,
value() {
- return ArrayMap.call(getInternalField(this, Items), (v: any, i: number) => i);
+ return ArrayMap.call(getHiddenField(this, Items), (v: any, i: number) => i);
},
},
values: {
@@ -66,7 +66,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
enumerable: true,
configurable: true,
value() {
- return getInternalField(this, Items);
+ return getHiddenField(this, Items);
},
},
[Symbol.iterator]: {
@@ -76,7 +76,7 @@ StaticNodeList.prototype = create(NodeList.prototype, {
let nextIndex = 0;
return {
next: () => {
- const items = getInternalField(this, Items);
+ const items = getHiddenField(this, Items);
return nextIndex < items.length
? {
value: items[nextIndex++],
@@ -110,7 +110,7 @@ setPrototypeOf(StaticNodeList, NodeList);
export function createStaticNodeList(items: T[]): NodeListOf {
const nodeList: NodeListOf = create(StaticNodeList.prototype);
- setInternalField(nodeList, Items, items);
+ setHiddenField(nodeList, Items, items);
// setting static indexes
forEach.call(items, (item: T, index: number) => {
defineProperty(nodeList, index, {
diff --git a/packages/integration-karma/test/shadow-dom/Node-properties/Node.cloneNode.spec.js b/packages/integration-karma/test/shadow-dom/Node-properties/Node.cloneNode.spec.js
index 64e99281a4..e9156cae86 100644
--- a/packages/integration-karma/test/shadow-dom/Node-properties/Node.cloneNode.spec.js
+++ b/packages/integration-karma/test/shadow-dom/Node-properties/Node.cloneNode.spec.js
@@ -55,6 +55,35 @@ describe('Node.cloneNode', () => {
});
});
+ describe('deep=undefined', () => {
+ it('should not clone shadow tree', () => {
+ const elm = createElement('x-slotted', { is: Slotted });
+ document.body.appendChild(elm);
+
+ const clone = elm.cloneNode();
+ expect(clone.childNodes.length).toBe(0);
+ expect(clone.outerHTML).toBe('');
+ });
+
+ it('should not clone slotted content', () => {
+ const elm = createElement('x-slotted', { is: Slotted });
+ document.body.appendChild(elm);
+
+ const clone = elm.shadowRoot.querySelector('x-container').cloneNode();
+ expect(clone.childNodes.length).toBe(0);
+ expect(clone.outerHTML).toBe('');
+ });
+
+ it('should not clone children of parent node with vanilla html', () => {
+ const table = document.createElement('table');
+ table.innerHTML = 'Cat |
---|
Dog |
';
+ document.body.appendChild(table);
+ const clone = table.cloneNode();
+ expect(clone.childNodes.length).toBe(0);
+ expect(clone.outerHTML).toBe('');
+ });
+ });
+
describe('deep=true', () => {
it('should not clone shadow tree', () => {
const elm = createElement('x-slotted', { is: Slotted });
@@ -95,5 +124,16 @@ describe('Node.cloneNode', () => {
expect(clone.childNodes.length).toBe(0);
expect(clone.outerHTML).toBe('');
});
+
+ it('should clone children of parent node with vanilla html', () => {
+ const table = document.createElement('table');
+ table.innerHTML = 'Cat |
---|
Dog |
';
+ document.body.appendChild(table);
+ const clone = table.cloneNode(true);
+ expect(clone.childNodes.length).toBe(1);
+ expect(clone.outerHTML).toBe(
+ ''
+ );
+ });
});
});