Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
function targetGetter(this: Event): EventTarget | null {
const originalCurrentTarget = eventCurrentTargetGetter.call(this);
const originalTarget = eventTargetGetter.call(this);
const composedPath = pathComposer(originalTarget, this.composed);
const doc = getOwnerDocument(originalTarget as Node);
// Handle cases where the currentTarget is null (for async events),
// and when an event has been added to Window
if (!(originalCurrentTarget instanceof Node)) {
// TODO: issue #1511 - Special escape hatch to support legacy behavior. Should be fixed.
// If the event's target is being accessed async and originalTarget is not a keyed element, do not retarget
if (isNull(originalCurrentTarget) && isUndefined(getNodeOwnerKey(originalTarget as Node))) {
return originalTarget;
}
return retarget(doc, composedPath);
} else if (originalCurrentTarget === doc || originalCurrentTarget === doc.body) {
// TODO: issue #1530 - If currentTarget is document or document.body (Third party libraries that have global event listeners)
// and the originalTarget is not a keyed element, do not retarget
if (isUndefined(getNodeOwnerKey(originalTarget as Node))) {
return originalTarget;
}
return retarget(doc, composedPath);
}
const eventContext = getEventContext(this);
const currentTarget =
eventContext === EventListenerContext.SHADOW_ROOT_LISTENER
? getShadowRoot(originalCurrentTarget as HTMLElement)
function getShadowParent(node: Node, value: ParentNode & Node): (Node & ParentNode) | null {
const owner = getNodeOwner(node);
if (value === owner) {
// walking up via parent chain might end up in the shadow root element
return getShadowRoot(owner);
} else if (value instanceof Element) {
if (getNodeNearestOwnerKey(node) === getNodeNearestOwnerKey(value)) {
// the element and its parent node belong to the same shadow root
return value;
} else if (!isNull(owner) && isSlotElement(value)) {
// slotted elements must be top level childNodes of the slot element
// where they slotted into, but its shadowed parent is always the
// owner of the slot.
const slotOwner = getNodeOwner(value);
if (!isNull(slotOwner) && isNodeOwnedBy(owner, slotOwner)) {
// it is a slotted element, and therefore its parent is always going to be the host of the slot
return slotOwner;
}
}
}
return null;
}
function getShadowParent(node: Node, value: ParentNode & Node): (Node & ParentNode) | null {
const owner = getNodeOwner(node);
if (value === owner) {
// walking up via parent chain might end up in the shadow root element
return getShadowRoot(owner);
} else if (value instanceof Element) {
if (getNodeNearestOwnerKey(node) === getNodeNearestOwnerKey(value)) {
// the element and its parent node belong to the same shadow root
return value;
} else if (!isNull(owner) && isSlotElement(value)) {
// slotted elements must be top level childNodes of the slot element
// where they slotted into, but its shadowed parent is always the
// owner of the slot.
const slotOwner = getNodeOwner(value);
if (!isNull(slotOwner) && isNodeOwnedBy(owner, slotOwner)) {
// it is a slotted element, and therefore its parent is always going to be the host of the slot
return slotOwner;
}
}
}
return null;
}
function getCtorProto(Ctor: any, subclassComponentName: string): ComponentConstructor {
let proto: ComponentConstructor | null = getPrototypeOf(Ctor);
if (isNull(proto)) {
throw new ReferenceError(
`Invalid prototype chain for ${subclassComponentName}, you must extend LightningElement.`
);
}
// covering the cases where the ref is circular in AMD
if (isCircularModuleDependency(proto)) {
const p = resolveCircularModuleDependency(proto);
if (process.env.NODE_ENV !== 'production') {
if (isNull(p)) {
throw new ReferenceError(
`Circular module dependency for ${subclassComponentName}, must resolve to a constructor that extends LightningElement.`
);
}
}
// escape hatch for Locker and other abstractions to provide their own base class instead
// of our Base class without having to leak it to user-land. If the circular function returns
export function getNodeNearestOwnerKey(node: Node): number | undefined {
let ownerNode: Node | null = node;
let ownerKey: number | undefined;
// search for the first element with owner identity (just in case of manually inserted elements)
while (!isNull(ownerNode)) {
ownerKey = ownerNode[OwnerKey];
if (!isUndefined(ownerKey)) {
return ownerKey;
}
ownerNode = parentNodeGetter.call(ownerNode);
}
}
pre: () => void,
job: () => void,
post: () => void
) {
let error;
pre();
try {
job();
} catch (e) {
error = Object(e);
} finally {
post();
if (!isUndefined(error)) {
error.wcStack = error.wcStack || getErrorComponentStack(vm.elm);
const errorBoundaryVm = isNull(owner) ? undefined : getErrorBoundaryVM(owner.elm);
if (isUndefined(errorBoundaryVm)) {
throw error; // eslint-disable-line no-unsafe-finally
}
resetShadowRoot(vm); // remove offenders
if (process.env.NODE_ENV !== 'production') {
startMeasure('errorCallback', errorBoundaryVm);
}
// error boundaries must have an ErrorCallback
const errorCallback = errorBoundaryVm.def.errorCallback!;
invokeComponentCallback(errorBoundaryVm, errorCallback, [error, error.wcStack]);
if (process.env.NODE_ENV !== 'production') {
endMeasure('errorCallback', errorBoundaryVm);
}
);
}
const hostKey = getNodeKey(host);
// this routine assumes that the node is coming from a different shadow (it is not owned by the host)
// just in case the provided node is not an element
let currentElement = node instanceof Element ? node : parentElementGetter.call(node);
while (!isNull(currentElement) && currentElement !== host) {
const elmOwnerKey = getNodeNearestOwnerKey(currentElement);
const parent = parentElementGetter.call(currentElement);
if (elmOwnerKey === hostKey) {
// we have reached an element inside the host's template, and only if
// that element is an slot, then the node is considered slotted
return isSlotElement(currentElement);
} else if (parent === host) {
return false;
} else if (!isNull(parent) && getNodeNearestOwnerKey(parent) !== elmOwnerKey) {
// we are crossing a boundary of some sort since the elm and its parent
// have different owner key. for slotted elements, this is possible
// if the parent happens to be a slot.
if (isSlotElement(parent)) {
/**
* the slot parent might be allocated inside another slot, think of:
* (<--- root element)
* (<--- own by x-root)
* (<--- own by x-root)
* (<--- own by x-child)
* (<--- own by x-parent)
* <div> (<--- own by x-root)
*
* while checking if x-parent has the div slotted, we need to traverse
* up, but when finding the first slot, we skip that one in favor of the
* most outer slot parent before jumping into its corresponding host.</div>
function focusOnNextOrBlur(
segment: HTMLElement[],
target: EventTarget,
relatedTarget: EventTarget
) {
const win = getOwnerWindow(relatedTarget as Node);
const next = getNextTabbable(segment, relatedTarget);
if (isNull(next)) {
// nothing to focus on, blur to invalidate the operation
muteFocusEventsDuringExecution(win, () => {
(target as HTMLElement).blur();
});
} else {
muteFocusEventsDuringExecution(win, () => {
next.focus();
});
}
}
function foldSlotElement(slot: HTMLElement) {
let parent = parentElementGetter.call(slot);
while (!isNull(parent) && isSlotElement(parent)) {
slot = parent as HTMLElement;
parent = parentElementGetter.call(slot);
}
return slot;
}
}
const proto = Ctor.prototype;
let {
connectedCallback,
disconnectedCallback,
renderedCallback,
errorCallback,
render,
} = proto;
const superProto = getCtorProto(Ctor, subclassComponentName);
const superDef: ComponentDef | null =
(superProto as any) !== BaseLightningElement
? getComponentDef(superProto, subclassComponentName)
: null;
const SuperBridge = isNull(superDef) ? BaseBridgeElement : superDef.bridge;
const bridge = HTMLBridgeElementFactory(
SuperBridge,
getOwnPropertyNames(props),
getOwnPropertyNames(methods)
);
if (!isNull(superDef)) {
props = assign(create(null), superDef.props, props);
methods = assign(create(null), superDef.methods, methods);
wire = superDef.wire || wire ? assign(create(null), superDef.wire, wire) : undefined;
track = assign(create(null), superDef.track, track);
connectedCallback = connectedCallback || superDef.connectedCallback;
disconnectedCallback = disconnectedCallback || superDef.disconnectedCallback;
renderedCallback = renderedCallback || superDef.renderedCallback;
errorCallback = errorCallback || superDef.errorCallback;
render = render || superDef.render;
template = template || superDef.template;