| 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 | const ATTRIBUTE_NAME_START_CHAR = |
| 13 | ':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'; |
| 14 | export const ATTRIBUTE_NAME_CHAR: string = |
| 15 | ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040'; |
| 16 | |
| 17 | const VALID_ATTRIBUTE_NAME_REGEX: RegExp = new RegExp( |
| 18 | '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$', |
| 19 | ); |
| 20 | |
| 21 | const illegalAttributeNameCache: {[string]: boolean} = {}; |
| 22 | const validatedAttributeNameCache: {[string]: boolean} = {}; |
| 23 | |
| 24 | export default function isAttributeNameSafe(attributeName: string): boolean { |
| 25 | if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { |
| 26 | return true; |
| 27 | } |
| 28 | if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { |
| 29 | return false; |
| 30 | } |
| 31 | if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { |
| 32 | validatedAttributeNameCache[attributeName] = true; |
| 33 | return true; |
| 34 | } |
| 35 | illegalAttributeNameCache[attributeName] = true; |
| 36 | if (__DEV__) { |
| 37 | console.error('Invalid attribute name: `%s`', attributeName); |
| 38 | } |
| 39 | return false; |
| 40 | } |