( message: ?string, lifetime: Reference, value: string | bigint | $ArrayBufferView, )
| 53 | : null; |
| 54 | |
| 55 | export function taintUniqueValue( |
| 56 | message: ?string, |
| 57 | lifetime: Reference, |
| 58 | value: string | bigint | $ArrayBufferView, |
| 59 | ): void { |
| 60 | if (!enableTaint) { |
| 61 | throw new Error('Not implemented.'); |
| 62 | } |
| 63 | // eslint-disable-next-line react-internal/safe-string-coercion |
| 64 | message = '' + (message || defaultMessage); |
| 65 | if ( |
| 66 | lifetime === null || |
| 67 | (typeof lifetime !== 'object' && typeof lifetime !== 'function') |
| 68 | ) { |
| 69 | throw new Error( |
| 70 | 'To taint a value, a lifetime must be defined by passing an object that holds ' + |
| 71 | 'the value.', |
| 72 | ); |
| 73 | } |
| 74 | let entryValue: string | bigint; |
| 75 | if (typeof value === 'string' || typeof value === 'bigint') { |
| 76 | // Use as is. |
| 77 | entryValue = value; |
| 78 | } else if ( |
| 79 | value instanceof TypedArrayConstructor || |
| 80 | value instanceof DataView |
| 81 | ) { |
| 82 | // For now, we just convert binary data to a string so that we can just use the native |
| 83 | // hashing in the Map implementation. It doesn't really matter what form the string |
| 84 | // take as long as it's the same when we look it up. |
| 85 | // We're not too worried about collisions since this should be a high entropy value. |
| 86 | TaintRegistryByteLengths.add(value.byteLength); |
| 87 | entryValue = binaryToComparableString(value); |
| 88 | } else { |
| 89 | const kind = value === null ? 'null' : typeof value; |
| 90 | if (kind === 'object' || kind === 'function') { |
| 91 | throw new Error( |
| 92 | 'taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.', |
| 93 | ); |
| 94 | } |
| 95 | throw new Error( |
| 96 | 'Cannot taint a ' + |
| 97 | kind + |
| 98 | ' because the value is too general and not unique enough to block globally.', |
| 99 | ); |
| 100 | } |
| 101 | const existingEntry = TaintRegistryValues.get(entryValue); |
| 102 | if (existingEntry === undefined) { |
| 103 | TaintRegistryValues.set(entryValue, { |
| 104 | message, |
| 105 | count: 1, |
| 106 | }); |
| 107 | } else { |
| 108 | existingEntry.count++; |
| 109 | } |
| 110 | if (finalizationRegistry !== null) { |
| 111 | finalizationRegistry.register(lifetime, entryValue); |
| 112 | } |
nothing calls this directly
no test coverage detected