All files / near-membrane-shared/src basic.ts

1.59% Statements 1/63
0% Branches 0/43
0% Functions 0/2
1.59% Lines 1/63

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221                                                                      14x                                                                                                                                                                                                                                                                                                                                                                                  
import { ArrayIsArray } from './Array';
import { ArrayBufferProtoByteLengthGetter } from './ArrayBuffer';
import { BigIntProtoValueOf, SUPPORTS_BIG_INT } from './BigInt';
import { BooleanProtoValueOf } from './Boolean';
import {
    TO_STRING_BRAND_ARRAY,
    TO_STRING_BRAND_ARRAY_BUFFER,
    TO_STRING_BRAND_BIG_INT,
    TO_STRING_BRAND_BOOLEAN,
    TO_STRING_BRAND_DATE,
    TO_STRING_BRAND_FUNCTION,
    TO_STRING_BRAND_MAP,
    TO_STRING_BRAND_NULL,
    TO_STRING_BRAND_NUMBER,
    TO_STRING_BRAND_OBJECT,
    TO_STRING_BRAND_REG_EXP,
    TO_STRING_BRAND_SET,
    TO_STRING_BRAND_STRING,
    TO_STRING_BRAND_SYMBOL,
    TO_STRING_BRAND_UNDEFINED,
    TO_STRING_BRAND_WEAK_MAP,
    TO_STRING_BRAND_WEAK_SET,
} from './constants';
import { DateProtoValueOf } from './Date';
import { MapProtoSizeGetter } from './Map';
import { NumberProtoValueOf } from './Number';
import { ObjectHasOwn, ObjectProtoToString } from './Object';
import { ReflectApply } from './Reflect';
import { RegExpProtoSourceGetter } from './RegExp';
import { SetProtoSizeGetter } from './Set';
import { StringProtoValueOf } from './String';
import { SymbolProtoValueOf } from './Symbol';
import { WeakMapProtoHas } from './WeakMap';
import { WeakSetProtoHas } from './WeakSet';
 
const { toStringTag: TO_STRING_TAG_SYMBOL } = Symbol;
 
function getBrandByTrialAndError(value: any): string {
    // Trail and error attempts are performed in order of most likely,
    // e.g. those values that have a @@toStringTag defined by default,
    // to least likely.
    //
    // Internally these brand checks rely on native methods that throw and catch
    // an exception when they operate on values with unexpected internal slot
    // entries.
 
    // Section 25.1.5.1 get ArrayBuffer.prototype.byteLength
    // https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.bytelength
    // Step 2: Perform RequireInternalSlot(O, [[ArrayBufferData]]).
    try {
        if ('byteLength' in value) {
            ReflectApply(ArrayBufferProtoByteLengthGetter, value, []);
            return TO_STRING_BRAND_ARRAY_BUFFER;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 21.4.4 Properties of the Date Prototype Object
    // https://tc39.es/ecma262/#thistimevalue
    // Step 1: If Type(value) is Object and value has a [[DateValue]] internal slot, then
    //     a. Return value.[[DateValue]].
    // Step 2: Throw a TypeError exception.
    try {
        if ('toLocaleDateString' in value) {
            ReflectApply(DateProtoValueOf, value, []);
            return TO_STRING_BRAND_DATE;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 24.1.3.10 get Map.prototype.size
    // https://tc39.es/ecma262/#sec-get-map.prototype.size
    // Step 2: Perform ? RequireInternalSlot(M, [[MapData]]).
    try {
        if ('get' in value && 'size' in value) {
            ReflectApply(MapProtoSizeGetter, value, []);
            return TO_STRING_BRAND_MAP;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 24.2.3.9 get Set.prototype.size
    // https://tc39.es/ecma262/#sec-get-set.prototype.size
    // Step 2: Perform ? RequireInternalSlot(S, [[SetData]]).
    try {
        if ('add' in value && 'size' in value) {
            ReflectApply(SetProtoSizeGetter, value, []);
            return TO_STRING_BRAND_SET;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 24.3.3.4 WeakMap.prototype.has ( key )
    // https://tc39.es/ecma262/#sec-weakmap.prototype.has
    // Step 2: Perform RequireInternalSlot(M, [[WeakMapData]]).
    try {
        if ('get' in value && !('size' in value)) {
            ReflectApply(WeakMapProtoHas, value, []);
            return TO_STRING_BRAND_WEAK_MAP;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 24.4.3.4 WeakSet.prototype.has ( value )
    // https://tc39.es/ecma262/#sec-weakset.prototype.has
    // Step 2: 2. Perform RequireInternalSlot(S, [[WeakSetData]]).
    try {
        if ('add' in value && !('size' in value)) {
            ReflectApply(WeakSetProtoHas, value, []);
            return TO_STRING_BRAND_WEAK_SET;
        }
        // eslint-disable-next-line no-empty
    } catch {}
 
    // The following checks are for the rare occurrence of object, i.e. boxed,
    // primitive values or those objects without a default @@toStringTag.
 
    // Section 21.1.3 Properties of the Number Prototype Object
    // https://tc39.es/ecma262/#thisnumbervalue
    // Step 2: If Type(value) is Object and value has a [[NumberData]] internal slot, then
    //     a. Let n be value.[[NumberData]].
    //     b. Assert: Type(n) is Number.
    try {
        if ('toPrecision' in value) {
            ReflectApply(NumberProtoValueOf, value, []);
            return TO_STRING_BRAND_NUMBER;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 20.4.3 Properties of the Symbol Prototype Object
    // https://tc39.es/ecma262/#thissymbolvalue
    // Step 2: If Type(value) is Object and value has a [[SymbolData]] internal slot, then
    //     a. Let s be value.[[SymbolData]].
    //     b. Assert: Type(s) is Symbol.
    try {
        if ('description' in value) {
            ReflectApply(SymbolProtoValueOf, value, []);
            return TO_STRING_BRAND_SYMBOL;
        }
        // eslint-disable-next-line no-empty
    } catch {}
 
    // Perform heavier checks last.
 
    // Section 22.2.6.13 get RegExp.prototype.source
    // https://tc39.es/ecma262/#sec-get-regexp.prototype.source
    // Step 3: If R does not have an [[OriginalSource]] internal slot, then
    //     a. If SameValue(R, %RegExp.prototype%) is true, return "(?:)".
    //     b. Otherwise, throw a TypeError exception.
    try {
        if (ObjectHasOwn(value, 'lastIndex')) {
            ReflectApply(RegExpProtoSourceGetter, value, []);
            return TO_STRING_BRAND_REG_EXP;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 22.1.3 Properties of the String Prototype Object
    // https://tc39.es/ecma262/#thisstringvalue
    // Step 2: If Type(value) is Object and value has a [[StringData]] internal slot, then
    //     a. Let s be value.[[StringData]].
    //     b. Assert: Type(s) is String.
    try {
        if (ObjectHasOwn(value, 'length')) {
            ReflectApply(StringProtoValueOf, value, []);
            return TO_STRING_BRAND_STRING;
        }
        // eslint-disable-next-line no-empty
    } catch {}
    // Section 20.3.3 Properties of the Boolean Prototype Object
    // https://tc39.es/ecma262/#thisbooleanvalue
    // Step 2: If Type(value) is Object and value has a [[BooleanData]] internal slot, then
    //     a. Let b be value.[[BooleanData]].
    //     b. Assert: Type(b) is Boolean.
    try {
        ReflectApply(BooleanProtoValueOf, value, []);
        return TO_STRING_BRAND_BOOLEAN;
        // eslint-disable-next-line no-empty
    } catch {}
    // istanbul ignore else: all platforms that LWS runs tests in support BigInt
    Iif (SUPPORTS_BIG_INT) {
        try {
            // Section 21.2.3 Properties of the BigInt Prototype Object
            // https://tc39.es/ecma262/#thisbigintvalue
            // Step 2: If Type(value) is Object and value has a [[BigIntData]] internal slot, then
            //     a. Assert: Type(value.[[BigIntData]]) is BigInt.
            ReflectApply(BigIntProtoValueOf!, value, []);
            return TO_STRING_BRAND_BIG_INT;
            // eslint-disable-next-line no-empty
        } catch {}
    }
    // Cannot detect brands for Arguments and Error objects.
    return TO_STRING_BRAND_OBJECT;
}
 
export function getBrand(value: any): string {
    // Section 20.1.3.6 Object.prototype.toString ( )
    // https://tc39.es/ecma262/#sec-object.prototype.tostring
    if (value === null) {
        return TO_STRING_BRAND_NULL;
    }
    if (value === undefined) {
        return TO_STRING_BRAND_UNDEFINED;
    }
    // eslint-disable-next-line default-case
    switch (typeof value) {
        case 'bigint':
            return TO_STRING_BRAND_BIG_INT;
        case 'boolean':
            return TO_STRING_BRAND_BOOLEAN;
        case 'function':
            return TO_STRING_BRAND_FUNCTION;
        case 'number':
            return TO_STRING_BRAND_NUMBER;
        case 'string':
            return TO_STRING_BRAND_STRING;
        case 'symbol':
            return TO_STRING_BRAND_SYMBOL;
    }
    if (ArrayIsArray(value)) {
        return TO_STRING_BRAND_ARRAY;
    }
    return TO_STRING_TAG_SYMBOL in value
        ? getBrandByTrialAndError(value)
        : ReflectApply(ObjectProtoToString, value, []);
}