1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import hasOwnProperty from 'shared/hasOwnProperty';
    
  11. 
    
  12. /* eslint-disable max-len */
    
  13. const ATTRIBUTE_NAME_START_CHAR =
    
  14.   ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
    
  15. /* eslint-enable max-len */
    
  16. export const ATTRIBUTE_NAME_CHAR: string =
    
  17.   ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
    
  18. 
    
  19. const VALID_ATTRIBUTE_NAME_REGEX: RegExp = new RegExp(
    
  20.   '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',
    
  21. );
    
  22. 
    
  23. const illegalAttributeNameCache: {[string]: boolean} = {};
    
  24. const validatedAttributeNameCache: {[string]: boolean} = {};
    
  25. 
    
  26. export default function isAttributeNameSafe(attributeName: string): boolean {
    
  27.   if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
    
  28.     return true;
    
  29.   }
    
  30.   if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {
    
  31.     return false;
    
  32.   }
    
  33.   if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
    
  34.     validatedAttributeNameCache[attributeName] = true;
    
  35.     return true;
    
  36.   }
    
  37.   illegalAttributeNameCache[attributeName] = true;
    
  38.   if (__DEV__) {
    
  39.     console.error('Invalid attribute name: `%s`', attributeName);
    
  40.   }
    
  41.   return false;
    
  42. }