import isAttributeNameSafe from '../shared/isAttributeNameSafe';
import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
import {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree';
import {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';
export function getValueForAttribute(
node: Element,
name: string,
expected: mixed,
): mixed {
if (__DEV__) {
if (!isAttributeNameSafe(name)) {
return;
}
if (!node.hasAttribute(name)) {
switch (typeof expected) {
case 'function':
case 'symbol':
return expected;
case 'boolean': {
const prefix = name.toLowerCase().slice(0, 5);
if (prefix !== 'data-' && prefix !== 'aria-') {
return expected;
}
}
}
return expected === undefined ? undefined : null;
}
const value = node.getAttribute(name);
if (__DEV__) {
checkAttributeStringCoercion(expected, name);
}
if (value === '' + (expected: any)) {
return expected;
}
return value;
}
}
export function getValueForAttributeOnCustomComponent(
node: Element,
name: string,
expected: mixed,
): mixed {
if (__DEV__) {
if (!isAttributeNameSafe(name)) {
return;
}
if (!node.hasAttribute(name)) {
switch (typeof expected) {
case 'symbol':
case 'object':
return expected;
case 'function':
return expected;
case 'boolean':
if (expected === false) {
return expected;
}
}
return expected === undefined ? undefined : null;
}
const value = node.getAttribute(name);
if (value === '' && expected === true) {
return true;
}
if (__DEV__) {
checkAttributeStringCoercion(expected, name);
}
if (value === '' + (expected: any)) {
return expected;
}
return value;
}
}
export function setValueForAttribute(
node: Element,
name: string,
value: mixed,
) {
if (isAttributeNameSafe(name)) {
if (value === null) {
node.removeAttribute(name);
return;
}
switch (typeof value) {
case 'undefined':
case 'function':
case 'symbol':
node.removeAttribute(name);
return;
case 'boolean': {
const prefix = name.toLowerCase().slice(0, 5);
if (prefix !== 'data-' && prefix !== 'aria-') {
node.removeAttribute(name);
return;
}
}
}
if (__DEV__) {
checkAttributeStringCoercion(value, name);
}
node.setAttribute(
name,
enableTrustedTypesIntegration ? (value: any) : '' + (value: any),
);
}
}
export function setValueForKnownAttribute(
node: Element,
name: string,
value: mixed,
) {
if (value === null) {
node.removeAttribute(name);
return;
}
switch (typeof value) {
case 'undefined':
case 'function':
case 'symbol':
case 'boolean': {
node.removeAttribute(name);
return;
}
}
if (__DEV__) {
checkAttributeStringCoercion(value, name);
}
node.setAttribute(
name,
enableTrustedTypesIntegration ? (value: any) : '' + (value: any),
);
}
export function setValueForNamespacedAttribute(
node: Element,
namespace: string,
name: string,
value: mixed,
) {
if (value === null) {
node.removeAttribute(name);
return;
}
switch (typeof value) {
case 'undefined':
case 'function':
case 'symbol':
case 'boolean': {
node.removeAttribute(name);
return;
}
}
if (__DEV__) {
checkAttributeStringCoercion(value, name);
}
node.setAttributeNS(
namespace,
name,
enableTrustedTypesIntegration ? (value: any) : '' + (value: any),
);
}
export function setValueForPropertyOnCustomComponent(
node: Element,
name: string,
value: mixed,
) {
if (name[0] === 'o' && name[1] === 'n') {
const useCapture = name.endsWith('Capture');
const eventName = name.slice(2, useCapture ? name.length - 7 : undefined);
const prevProps = getFiberCurrentPropsFromNode(node);
const prevValue = prevProps != null ? prevProps[name] : null;
if (typeof prevValue === 'function') {
node.removeEventListener(eventName, prevValue, useCapture);
}
if (typeof value === 'function') {
if (typeof prevValue !== 'function' && prevValue !== null) {
if (name in (node: any)) {
(node: any)[name] = null;
} else if (node.hasAttribute(name)) {
node.removeAttribute(name);
}
}
node.addEventListener(eventName, (value: EventListener), useCapture);
return;
}
}
trackHostMutation();
if (name in (node: any)) {
(node: any)[name] = value;
return;
}
if (value === true) {
node.setAttribute(name, '');
return;
}
setValueForAttribute(node, name, value);
}