UNPKG

mapshaper

Version:

A tool for editing geospatial data for mapping and GIS.

1,644 lines (1,378 loc) 2.81 MB
(function () { 'use strict'; const THIS_IS_NOT_AN_OBJECT = "This is not an object"; const THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = "This is not a Float16Array object"; const THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY = "This constructor is not a subclass of Float16Array"; const THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT = "The constructor property value is not an object"; const SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT = "Species constructor didn't return TypedArray object"; const DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH = "Derived constructor created TypedArray object which was too small length"; const ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER = "Attempting to access detached ArrayBuffer"; const CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT = "Cannot convert undefined or null to object"; const CANNOT_MIX_BIGINT_AND_OTHER_TYPES = "Cannot mix BigInt and other types, use explicit conversions"; const ITERATOR_PROPERTY_IS_NOT_CALLABLE = "@@iterator property is not callable"; const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE = "Reduce of empty array with no initial value"; const THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED = "The comparison function must be either a function or undefined"; const OFFSET_IS_OUT_OF_BOUNDS = "Offset is out of bounds"; /* eslint-disable no-restricted-globals, no-restricted-syntax */ /* global SharedArrayBuffer */ /** @type {<T extends (...args: any) => any>(target: T) => (thisArg: ThisType<T>, ...args: any[]) => any} */ function uncurryThis(target) { return (thisArg, ...args) => { return ReflectApply(target, thisArg, args); }; } /** @type {(target: any, key: string | symbol) => (thisArg: any, ...args: any[]) => any} */ function uncurryThisGetter(target, key) { return uncurryThis( ReflectGetOwnPropertyDescriptor( target, key ).get ); } // Reflect const { apply: ReflectApply, construct: ReflectConstruct, defineProperty: ReflectDefineProperty, get: ReflectGet, getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor, getPrototypeOf: ReflectGetPrototypeOf, has: ReflectHas, ownKeys: ReflectOwnKeys, set: ReflectSet, setPrototypeOf: ReflectSetPrototypeOf, } = Reflect; // Proxy const NativeProxy = Proxy; // Number const { EPSILON, MAX_SAFE_INTEGER, isFinite: NumberIsFinite, isNaN: NumberIsNaN, } = Number; // Symbol const { iterator: SymbolIterator, species: SymbolSpecies, toStringTag: SymbolToStringTag, for: SymbolFor, } = Symbol; // Object const NativeObject = Object; const { create: ObjectCreate, defineProperty: ObjectDefineProperty, freeze: ObjectFreeze, is: ObjectIs, } = NativeObject; const ObjectPrototype = NativeObject.prototype; /** @type {(object: object, key: PropertyKey) => Function | undefined} */ const ObjectPrototype__lookupGetter__ = /** @type {any} */ (ObjectPrototype).__lookupGetter__ ? uncurryThis(/** @type {any} */ (ObjectPrototype).__lookupGetter__) : (object, key) => { if (object == null) { throw NativeTypeError( CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT ); } let target = NativeObject(object); do { const descriptor = ReflectGetOwnPropertyDescriptor(target, key); if (descriptor !== undefined) { if (ObjectHasOwn(descriptor, "get")) { return descriptor.get; } return; } } while ((target = ReflectGetPrototypeOf(target)) !== null); }; /** @type {(object: object, key: PropertyKey) => boolean} */ const ObjectHasOwn = /** @type {any} */ (NativeObject).hasOwn || uncurryThis(ObjectPrototype.hasOwnProperty); // Array const NativeArray = Array; const ArrayIsArray = NativeArray.isArray; const ArrayPrototype = NativeArray.prototype; /** @type {(array: ArrayLike<unknown>, separator?: string) => string} */ const ArrayPrototypeJoin = uncurryThis(ArrayPrototype.join); /** @type {<T>(array: T[], ...items: T[]) => number} */ const ArrayPrototypePush = uncurryThis(ArrayPrototype.push); /** @type {(array: ArrayLike<unknown>, ...opts: any[]) => string} */ const ArrayPrototypeToLocaleString = uncurryThis( ArrayPrototype.toLocaleString ); const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator]; /** @type {<T>(array: T[]) => IterableIterator<T>} */ const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator); // Math const { abs: MathAbs, trunc: MathTrunc, } = Math; // ArrayBuffer const NativeArrayBuffer = ArrayBuffer; const ArrayBufferIsView = NativeArrayBuffer.isView; const ArrayBufferPrototype = NativeArrayBuffer.prototype; /** @type {(buffer: ArrayBuffer, begin?: number, end?: number) => number} */ const ArrayBufferPrototypeSlice = uncurryThis(ArrayBufferPrototype.slice); /** @type {(buffer: ArrayBuffer) => ArrayBuffer} */ const ArrayBufferPrototypeGetByteLength = uncurryThisGetter(ArrayBufferPrototype, "byteLength"); // SharedArrayBuffer const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : null; /** @type {(buffer: SharedArrayBuffer) => SharedArrayBuffer} */ const SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer && uncurryThisGetter(NativeSharedArrayBuffer.prototype, "byteLength"); // TypedArray /** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */ /** @type {any} */ const TypedArray = ReflectGetPrototypeOf(Uint8Array); const TypedArrayFrom = TypedArray.from; const TypedArrayPrototype = TypedArray.prototype; const NativeTypedArrayPrototypeSymbolIterator = TypedArrayPrototype[SymbolIterator]; /** @type {(typedArray: TypedArray) => IterableIterator<number>} */ const TypedArrayPrototypeKeys = uncurryThis(TypedArrayPrototype.keys); /** @type {(typedArray: TypedArray) => IterableIterator<number>} */ const TypedArrayPrototypeValues = uncurryThis( TypedArrayPrototype.values ); /** @type {(typedArray: TypedArray) => IterableIterator<[number, number]>} */ const TypedArrayPrototypeEntries = uncurryThis( TypedArrayPrototype.entries ); /** @type {(typedArray: TypedArray, array: ArrayLike<number>, offset?: number) => void} */ const TypedArrayPrototypeSet = uncurryThis(TypedArrayPrototype.set); /** @type {<T extends TypedArray>(typedArray: T) => T} */ const TypedArrayPrototypeReverse = uncurryThis( TypedArrayPrototype.reverse ); /** @type {<T extends TypedArray>(typedArray: T, value: number, start?: number, end?: number) => T} */ const TypedArrayPrototypeFill = uncurryThis(TypedArrayPrototype.fill); /** @type {<T extends TypedArray>(typedArray: T, target: number, start: number, end?: number) => T} */ const TypedArrayPrototypeCopyWithin = uncurryThis( TypedArrayPrototype.copyWithin ); /** @type {<T extends TypedArray>(typedArray: T, compareFn?: (a: number, b: number) => number) => T} */ const TypedArrayPrototypeSort = uncurryThis(TypedArrayPrototype.sort); /** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */ const TypedArrayPrototypeSlice = uncurryThis(TypedArrayPrototype.slice); /** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */ const TypedArrayPrototypeSubarray = uncurryThis( TypedArrayPrototype.subarray ); /** @type {((typedArray: TypedArray) => ArrayBuffer)} */ const TypedArrayPrototypeGetBuffer = uncurryThisGetter( TypedArrayPrototype, "buffer" ); /** @type {((typedArray: TypedArray) => number)} */ const TypedArrayPrototypeGetByteOffset = uncurryThisGetter( TypedArrayPrototype, "byteOffset" ); /** @type {((typedArray: TypedArray) => number)} */ const TypedArrayPrototypeGetLength = uncurryThisGetter( TypedArrayPrototype, "length" ); /** @type {(target: unknown) => string} */ const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter( TypedArrayPrototype, SymbolToStringTag ); // Uint8Array const NativeUint8Array = Uint8Array; // Uint16Array const NativeUint16Array = Uint16Array; /** @type {Uint16ArrayConstructor["from"]} */ const Uint16ArrayFrom = (...args) => { return ReflectApply(TypedArrayFrom, NativeUint16Array, args); }; // Uint32Array const NativeUint32Array = Uint32Array; // Float32Array const NativeFloat32Array = Float32Array; // ArrayIterator /** @type {any} */ const ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]()); /** @type {<T>(arrayIterator: IterableIterator<T>) => IteratorResult<T>} */ const ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next); // Generator /** @type {<T = unknown, TReturn = any, TNext = unknown>(generator: Generator<T, TReturn, TNext>, value?: TNext) => T} */ const GeneratorPrototypeNext = uncurryThis((function* () {})().next); // Iterator const IteratorPrototype = ReflectGetPrototypeOf(ArrayIteratorPrototype); // DataView const DataViewPrototype = DataView.prototype; /** @type {(dataView: DataView, byteOffset: number, littleEndian?: boolean) => number} */ const DataViewPrototypeGetUint16 = uncurryThis( DataViewPrototype.getUint16 ); /** @type {(dataView: DataView, byteOffset: number, value: number, littleEndian?: boolean) => void} */ const DataViewPrototypeSetUint16 = uncurryThis( DataViewPrototype.setUint16 ); // Error const NativeTypeError = TypeError; const NativeRangeError = RangeError; // WeakSet /** * Do not construct with arguments to avoid calling the "add" method * @type {{new <T extends {}>(): WeakSet<T>}} */ const NativeWeakSet = WeakSet; const WeakSetPrototype = NativeWeakSet.prototype; /** @type {<T extends {}>(set: WeakSet<T>, value: T) => Set<T>} */ const WeakSetPrototypeAdd = uncurryThis(WeakSetPrototype.add); /** @type {<T extends {}>(set: WeakSet<T>, value: T) => boolean} */ const WeakSetPrototypeHas = uncurryThis(WeakSetPrototype.has); // WeakMap /** * Do not construct with arguments to avoid calling the "set" method * @type {{new <K extends {}, V>(): WeakMap<K, V>}} */ const NativeWeakMap = WeakMap; const WeakMapPrototype = NativeWeakMap.prototype; /** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => V} */ const WeakMapPrototypeGet = uncurryThis(WeakMapPrototype.get); /** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K) => boolean} */ const WeakMapPrototypeHas = uncurryThis(WeakMapPrototype.has); /** @type {<K extends {}, V>(weakMap: WeakMap<K, V>, key: K, value: V) => WeakMap} */ const WeakMapPrototypeSet = uncurryThis(WeakMapPrototype.set); /** @type {WeakMap<{}, IterableIterator<any>>} */ const arrayIterators = new NativeWeakMap(); const SafeIteratorPrototype = ObjectCreate(null, { next: { value: function next() { const arrayIterator = WeakMapPrototypeGet(arrayIterators, this); return ArrayIteratorPrototypeNext(arrayIterator); }, }, [SymbolIterator]: { value: function values() { return this; }, }, }); /** * Wrap the Array around the SafeIterator If Array.prototype [@@iterator] has been modified * @type {<T>(array: T[]) => Iterable<T>} */ function safeIfNeeded(array) { if ( array[SymbolIterator] === NativeArrayPrototypeSymbolIterator && ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext ) { return array; } const safe = ObjectCreate(SafeIteratorPrototype); WeakMapPrototypeSet(arrayIterators, safe, ArrayPrototypeSymbolIterator(array)); return safe; } /** @type {WeakMap<{}, Generator<any>>} */ const generators = new NativeWeakMap(); /** @see https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object */ const DummyArrayIteratorPrototype = ObjectCreate(IteratorPrototype, { next: { value: function next() { const generator = WeakMapPrototypeGet(generators, this); return GeneratorPrototypeNext(generator); }, writable: true, configurable: true, }, }); for (const key of ReflectOwnKeys(ArrayIteratorPrototype)) { // next method has already defined if (key === "next") { continue; } // Copy ArrayIteratorPrototype descriptors to DummyArrayIteratorPrototype ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key)); } /** * Wrap the Generator around the dummy ArrayIterator * @type {<T>(generator: Generator<T>) => IterableIterator<T>} */ function wrap(generator) { const dummy = ObjectCreate(DummyArrayIteratorPrototype); WeakMapPrototypeSet(generators, dummy, generator); return dummy; } /** * @param {unknown} value * @returns {value is {}} */ function isObject$1(value) { return ( (value !== null && typeof value === "object") || typeof value === "function" ); } /** * @param {unknown} value * @returns {value is {}} */ function isObjectLike(value) { return value !== null && typeof value === "object"; } // Inspired by util.types implementation of Node.js /** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */ /** * @param {unknown} value * @returns {value is TypedArray} */ function isNativeTypedArray(value) { return TypedArrayPrototypeGetSymbolToStringTag(value) !== undefined; } /** * @param {unknown} value * @returns {value is BigInt64Array|BigUint64Array} */ function isNativeBigIntTypedArray(value) { const typedArrayName = TypedArrayPrototypeGetSymbolToStringTag(value); return ( typedArrayName === "BigInt64Array" || typedArrayName === "BigUint64Array" ); } /** * @param {unknown} value * @returns {value is ArrayBuffer} */ function isArrayBuffer(value) { try { // ArrayBuffers are never arrays if (ArrayIsArray(value)) { return false; } ArrayBufferPrototypeGetByteLength(/** @type {any} */ (value)); return true; } catch (e) { return false; } } /** * @param {unknown} value * @returns {value is SharedArrayBuffer} */ function isSharedArrayBuffer(value) { if (NativeSharedArrayBuffer === null) { return false; } try { SharedArrayBufferPrototypeGetByteLength(/** @type {any} */ (value)); return true; } catch (e) { return false; } } /** * @param {unknown} value * @returns {value is ArrayBuffer|SharedArrayBuffer} */ function isAnyArrayBuffer(value) { return isArrayBuffer(value) || isSharedArrayBuffer(value); } /** * @param {unknown} value * @returns {value is unknown[]} */ function isOrdinaryArray(value) { if (!ArrayIsArray(value)) { return false; } // Verify that there are no changes in ArrayIterator return ( value[SymbolIterator] === NativeArrayPrototypeSymbolIterator && ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext ); } /** * @param {unknown} value * @returns {value is TypedArray} */ function isOrdinaryNativeTypedArray(value) { if (!isNativeTypedArray(value)) { return false; } // Verify that there are no changes in ArrayIterator return ( value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator && ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext ); } /** * @param {unknown} value * @returns {value is string} */ function isCanonicalIntegerIndexString(value) { if (typeof value !== "string") { return false; } const number = +value; if (value !== number + "") { return false; } if (!NumberIsFinite(number)) { return false; } return number === MathTrunc(number); } const brand = SymbolFor("__Float16Array__"); /** * @param {unknown} target * @throws {TypeError} * @returns {boolean} */ function hasFloat16ArrayBrand(target) { if (!isObjectLike(target)) { return false; } const prototype = ReflectGetPrototypeOf(target); if (!isObjectLike(prototype)) { return false; } const constructor = prototype.constructor; if (constructor === undefined) { return false; } if (!isObject$1(constructor)) { throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT); } return ReflectHas(constructor, brand); } const INVERSE_OF_EPSILON = 1 / EPSILON; /** * rounds to the nearest value; * if the number falls midway, it is rounded to the nearest value with an even least significant digit * @param {number} num * @returns {number} */ function roundTiesToEven(num) { return (num + INVERSE_OF_EPSILON) - INVERSE_OF_EPSILON; } const FLOAT16_MIN_VALUE = 6.103515625e-05; const FLOAT16_MAX_VALUE = 65504; const FLOAT16_EPSILON = 0.0009765625; const FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE; const FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON; /** * round a number to a half float number * @param {unknown} num - double float * @returns {number} half float number */ function roundToFloat16(num) { const number = +num; // NaN, Infinity, -Infinity, 0, -0 if (!NumberIsFinite(number) || number === 0) { return number; } // finite except 0, -0 const sign = number > 0 ? 1 : -1; const absolute = MathAbs(number); // small number if (absolute < FLOAT16_MIN_VALUE) { return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE; } const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute; const result = temp - (temp - absolute); // large number if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) { return sign * Infinity; } return sign * result; } // base algorithm: http://fox-toolkit.org/ftp/fasthalffloatconversion.pdf const buffer = new NativeArrayBuffer(4); const floatView = new NativeFloat32Array(buffer); const uint32View = new NativeUint32Array(buffer); const baseTable = new NativeUint16Array(512); const shiftTable = new NativeUint8Array(512); for (let i = 0; i < 256; ++i) { const e = i - 127; // very small number (0, -0) if (e < -24) { baseTable[i] = 0x0000; baseTable[i | 0x100] = 0x8000; shiftTable[i] = 24; shiftTable[i | 0x100] = 24; // small number (denorm) } else if (e < -14) { baseTable[i] = 0x0400 >> (-e - 14); baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000; shiftTable[i] = -e - 1; shiftTable[i | 0x100] = -e - 1; // normal number } else if (e <= 15) { baseTable[i] = (e + 15) << 10; baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000; shiftTable[i] = 13; shiftTable[i | 0x100] = 13; // large number (Infinity, -Infinity) } else if (e < 128) { baseTable[i] = 0x7c00; baseTable[i | 0x100] = 0xfc00; shiftTable[i] = 24; shiftTable[i | 0x100] = 24; // stay (NaN, Infinity, -Infinity) } else { baseTable[i] = 0x7c00; baseTable[i | 0x100] = 0xfc00; shiftTable[i] = 13; shiftTable[i | 0x100] = 13; } } /** * round a number to a half float number bits * @param {unknown} num - double float * @returns {number} half float number bits */ function roundToFloat16Bits(num) { floatView[0] = roundToFloat16(num); const f = uint32View[0]; const e = (f >> 23) & 0x1ff; return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]); } const mantissaTable = new NativeUint32Array(2048); for (let i = 1; i < 1024; ++i) { let m = i << 13; // zero pad mantissa bits let e = 0; // zero exponent // normalized while ((m & 0x00800000) === 0) { m <<= 1; e -= 0x00800000; // decrement exponent } m &= ~0x00800000; // clear leading 1 bit e += 0x38800000; // adjust bias mantissaTable[i] = m | e; } for (let i = 1024; i < 2048; ++i) { mantissaTable[i] = 0x38000000 + ((i - 1024) << 13); } const exponentTable = new NativeUint32Array(64); for (let i = 1; i < 31; ++i) { exponentTable[i] = i << 23; } exponentTable[31] = 0x47800000; exponentTable[32] = 0x80000000; for (let i = 33; i < 63; ++i) { exponentTable[i] = 0x80000000 + ((i - 32) << 23); } exponentTable[63] = 0xc7800000; const offsetTable = new NativeUint16Array(64); for (let i = 1; i < 64; ++i) { if (i !== 32) { offsetTable[i] = 1024; } } /** * convert a half float number bits to a number * @param {number} float16bits - half float number bits * @returns {number} double float */ function convertToNumber(float16bits) { const i = float16bits >> 10; uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i]; return floatView[0]; } /** * @see https://tc39.es/ecma262/#sec-tointegerorinfinity * @param {unknown} target * @returns {number} */ function ToIntegerOrInfinity(target) { const number = +target; if (NumberIsNaN(number) || number === 0) { return 0; } return MathTrunc(number); } /** * @see https://tc39.es/ecma262/#sec-tolength * @param {unknown} target * @returns {number} */ function ToLength(target) { const length = ToIntegerOrInfinity(target); if (length < 0) { return 0; } return length < MAX_SAFE_INTEGER ? length : MAX_SAFE_INTEGER; } /** * @see https://tc39.es/ecma262/#sec-speciesconstructor * @param {object} target * @param {{ new(...args: any[]): any; }} defaultConstructor * @returns {{ new(...args: any[]): any; }} */ function SpeciesConstructor(target, defaultConstructor) { if (!isObject$1(target)) { throw NativeTypeError(THIS_IS_NOT_AN_OBJECT); } const constructor = target.constructor; if (constructor === undefined) { return defaultConstructor; } if (!isObject$1(constructor)) { throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT); } const species = constructor[SymbolSpecies]; if (species == null) { return defaultConstructor; } return species; } /** * @see https://tc39.es/ecma262/#sec-isdetachedbuffer * @param {ArrayBufferLike} buffer * @returns {boolean} */ function IsDetachedBuffer(buffer) { if (isSharedArrayBuffer(buffer)) { return false; } try { ArrayBufferPrototypeSlice(buffer, 0, 0); return false; } catch (e) {/* empty */} return true; } /** * bigint comparisons are not supported * @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort * @param {number} x * @param {number} y * @returns {-1 | 0 | 1} */ function defaultCompare(x, y) { const isXNaN = NumberIsNaN(x); const isYNaN = NumberIsNaN(y); if (isXNaN && isYNaN) { return 0; } if (isXNaN) { return 1; } if (isYNaN) { return -1; } if (x < y) { return -1; } if (x > y) { return 1; } if (x === 0 && y === 0) { const isXPlusZero = ObjectIs(x, 0); const isYPlusZero = ObjectIs(y, 0); if (!isXPlusZero && isYPlusZero) { return -1; } if (isXPlusZero && !isYPlusZero) { return 1; } } return 0; } const BYTES_PER_ELEMENT = 2; /** @typedef {Uint16Array & { __float16bits: never }} Float16BitsArray */ /** @type {WeakMap<Float16Array, Float16BitsArray>} */ const float16bitsArrays = new NativeWeakMap(); /** * @param {unknown} target * @returns {target is Float16Array} */ function isFloat16Array(target) { return WeakMapPrototypeHas(float16bitsArrays, target) || (!ArrayBufferIsView(target) && hasFloat16ArrayBrand(target)); } /** * @param {unknown} target * @throws {TypeError} * @returns {asserts target is Float16Array} */ function assertFloat16Array(target) { if (!isFloat16Array(target)) { throw NativeTypeError(THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT); } } /** * @param {unknown} target * @param {number=} count * @throws {TypeError} * @returns {asserts target is Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float16Array|Float32Array|Float64Array} */ function assertSpeciesTypedArray(target, count) { const isTargetFloat16Array = isFloat16Array(target); const isTargetTypedArray = isNativeTypedArray(target); if (!isTargetFloat16Array && !isTargetTypedArray) { throw NativeTypeError(SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT); } if (typeof count === "number") { let length; if (isTargetFloat16Array) { const float16bitsArray = getFloat16BitsArray(target); length = TypedArrayPrototypeGetLength(float16bitsArray); } else { length = TypedArrayPrototypeGetLength(target); } if (length < count) { throw NativeTypeError( DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH ); } } if (isNativeBigIntTypedArray(target)) { throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES); } } /** * @param {Float16Array} float16 * @throws {TypeError} * @returns {Float16BitsArray} */ function getFloat16BitsArray(float16) { const float16bitsArray = WeakMapPrototypeGet(float16bitsArrays, float16); if (float16bitsArray !== undefined) { const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray); if (IsDetachedBuffer(buffer)) { throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER); } return float16bitsArray; } // from another Float16Array instance (a different version?) const buffer = /** @type {any} */ (float16).buffer; if (IsDetachedBuffer(buffer)) { throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER); } const cloned = ReflectConstruct(Float16Array, [ buffer, /** @type {any} */ (float16).byteOffset, /** @type {any} */ (float16).length, ], float16.constructor); return WeakMapPrototypeGet(float16bitsArrays, cloned); } /** * @param {Float16BitsArray} float16bitsArray * @returns {number[]} */ function copyToArray(float16bitsArray) { const length = TypedArrayPrototypeGetLength(float16bitsArray); const array = []; for (let i = 0; i < length; ++i) { array[i] = convertToNumber(float16bitsArray[i]); } return array; } /** @type {WeakSet<Function>} */ const TypedArrayPrototypeGetters = new NativeWeakSet(); for (const key of ReflectOwnKeys(TypedArrayPrototype)) { // @@toStringTag getter property is defined in Float16Array.prototype if (key === SymbolToStringTag) { continue; } const descriptor = ReflectGetOwnPropertyDescriptor(TypedArrayPrototype, key); if (ObjectHasOwn(descriptor, "get") && typeof descriptor.get === "function") { WeakSetPrototypeAdd(TypedArrayPrototypeGetters, descriptor.get); } } const handler = ObjectFreeze(/** @type {ProxyHandler<Float16BitsArray>} */ ({ get(target, key, receiver) { if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) { return convertToNumber(ReflectGet(target, key)); } // %TypedArray%.prototype getter properties cannot called by Proxy receiver if (WeakSetPrototypeHas(TypedArrayPrototypeGetters, ObjectPrototype__lookupGetter__(target, key))) { return ReflectGet(target, key); } return ReflectGet(target, key, receiver); }, set(target, key, value, receiver) { if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) { return ReflectSet(target, key, roundToFloat16Bits(value)); } return ReflectSet(target, key, value, receiver); }, getOwnPropertyDescriptor(target, key) { if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) { const descriptor = ReflectGetOwnPropertyDescriptor(target, key); descriptor.value = convertToNumber(descriptor.value); return descriptor; } return ReflectGetOwnPropertyDescriptor(target, key); }, defineProperty(target, key, descriptor) { if ( isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key) && ObjectHasOwn(descriptor, "value") ) { descriptor.value = roundToFloat16Bits(descriptor.value); return ReflectDefineProperty(target, key, descriptor); } return ReflectDefineProperty(target, key, descriptor); }, })); class Float16Array { /** @see https://tc39.es/ecma262/#sec-typedarray */ constructor(input, _byteOffset, _length) { /** @type {Float16BitsArray} */ let float16bitsArray; if (isFloat16Array(input)) { float16bitsArray = ReflectConstruct(NativeUint16Array, [getFloat16BitsArray(input)], new.target); } else if (isObject$1(input) && !isAnyArrayBuffer(input)) { // object without ArrayBuffer, SharedArrayBuffer /** @type {ArrayLike<unknown>} */ let list; /** @type {number} */ let length; if (isNativeTypedArray(input)) { // TypedArray list = input; length = TypedArrayPrototypeGetLength(input); const buffer = TypedArrayPrototypeGetBuffer(input); if (IsDetachedBuffer(buffer)) { throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER); } if (isNativeBigIntTypedArray(input)) { throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES); } const data = new NativeArrayBuffer( length * BYTES_PER_ELEMENT ); float16bitsArray = ReflectConstruct(NativeUint16Array, [data], new.target); } else { const iterator = input[SymbolIterator]; if (iterator != null && typeof iterator !== "function") { throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE); } if (iterator != null) { // Iterable (Array) // for optimization if (isOrdinaryArray(input)) { list = input; length = input.length; } else { // eslint-disable-next-line no-restricted-syntax list = [... /** @type {Iterable<unknown>} */ (input)]; length = list.length; } } else { // ArrayLike list = /** @type {ArrayLike<unknown>} */ (input); length = ToLength(list.length); } float16bitsArray = ReflectConstruct(NativeUint16Array, [length], new.target); } // set values for (let i = 0; i < length; ++i) { float16bitsArray[i] = roundToFloat16Bits(list[i]); } } else { // primitive, ArrayBuffer, SharedArrayBuffer float16bitsArray = ReflectConstruct(NativeUint16Array, arguments, new.target); } /** @type {Float16Array} */ const proxy = /** @type {any} */ (new NativeProxy(float16bitsArray, handler)); // proxy private storage WeakMapPrototypeSet(float16bitsArrays, proxy, float16bitsArray); return proxy; } /** * limitation: `Object.getOwnPropertyNames(Float16Array)` or `Reflect.ownKeys(Float16Array)` include this key * @see https://tc39.es/ecma262/#sec-%typedarray%.from */ static from(src, ...opts) { const Constructor = this; if (!ReflectHas(Constructor, brand)) { throw NativeTypeError( THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY ); } // for optimization if (Constructor === Float16Array) { if (isFloat16Array(src) && opts.length === 0) { const float16bitsArray = getFloat16BitsArray(src); const uint16 = new NativeUint16Array( TypedArrayPrototypeGetBuffer(float16bitsArray), TypedArrayPrototypeGetByteOffset(float16bitsArray), TypedArrayPrototypeGetLength(float16bitsArray) ); return new Float16Array( TypedArrayPrototypeGetBuffer(TypedArrayPrototypeSlice(uint16)) ); } if (opts.length === 0) { return new Float16Array( TypedArrayPrototypeGetBuffer( Uint16ArrayFrom(src, roundToFloat16Bits) ) ); } const mapFunc = opts[0]; const thisArg = opts[1]; return new Float16Array( TypedArrayPrototypeGetBuffer( Uint16ArrayFrom(src, function (val, ...args) { return roundToFloat16Bits( ReflectApply(mapFunc, this, [val, ...safeIfNeeded(args)]) ); }, thisArg) ) ); } /** @type {ArrayLike<unknown>} */ let list; /** @type {number} */ let length; const iterator = src[SymbolIterator]; if (iterator != null && typeof iterator !== "function") { throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE); } if (iterator != null) { // Iterable (TypedArray, Array) // for optimization if (isOrdinaryArray(src)) { list = src; length = src.length; } else if (isOrdinaryNativeTypedArray(src)) { list = src; length = TypedArrayPrototypeGetLength(src); } else { // eslint-disable-next-line no-restricted-syntax list = [...src]; length = list.length; } } else { // ArrayLike if (src == null) { throw NativeTypeError( CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT ); } list = NativeObject(src); length = ToLength(list.length); } const array = new Constructor(length); if (opts.length === 0) { for (let i = 0; i < length; ++i) { array[i] = /** @type {number} */ (list[i]); } } else { const mapFunc = opts[0]; const thisArg = opts[1]; for (let i = 0; i < length; ++i) { array[i] = ReflectApply(mapFunc, thisArg, [list[i], i]); } } return array; } /** * limitation: `Object.getOwnPropertyNames(Float16Array)` or `Reflect.ownKeys(Float16Array)` include this key * @see https://tc39.es/ecma262/#sec-%typedarray%.of */ static of(...items) { const Constructor = this; if (!ReflectHas(Constructor, brand)) { throw NativeTypeError( THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY ); } const length = items.length; // for optimization if (Constructor === Float16Array) { const proxy = new Float16Array(length); const float16bitsArray = getFloat16BitsArray(proxy); for (let i = 0; i < length; ++i) { float16bitsArray[i] = roundToFloat16Bits(items[i]); } return proxy; } const array = new Constructor(length); for (let i = 0; i < length; ++i) { array[i] = items[i]; } return array; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys */ keys() { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); return TypedArrayPrototypeKeys(float16bitsArray); } /** * limitation: returns a object whose prototype is not `%ArrayIteratorPrototype%` * @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.values */ values() { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); return wrap((function* () { // eslint-disable-next-line no-restricted-syntax for (const val of TypedArrayPrototypeValues(float16bitsArray)) { yield convertToNumber(val); } })()); } /** * limitation: returns a object whose prototype is not `%ArrayIteratorPrototype%` * @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries */ entries() { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); return wrap((function* () { // eslint-disable-next-line no-restricted-syntax for (const [i, val] of TypedArrayPrototypeEntries(float16bitsArray)) { yield /** @type {[number, number]} */ ([i, convertToNumber(val)]); } })()); } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.at */ at(index) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const relativeIndex = ToIntegerOrInfinity(index); const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; if (k < 0 || k >= length) { return; } return convertToNumber(float16bitsArray[k]); } /** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with */ with(index, value) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const relativeIndex = ToIntegerOrInfinity(index); const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; const number = +value; if (k < 0 || k >= length) { throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS); } // don't use SpeciesConstructor const uint16 = new NativeUint16Array( TypedArrayPrototypeGetBuffer(float16bitsArray), TypedArrayPrototypeGetByteOffset(float16bitsArray), TypedArrayPrototypeGetLength(float16bitsArray) ); const cloned = new Float16Array( TypedArrayPrototypeGetBuffer( TypedArrayPrototypeSlice(uint16) ) ); const array = getFloat16BitsArray(cloned); array[k] = roundToFloat16Bits(number); return cloned; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.map */ map(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; const Constructor = SpeciesConstructor(float16bitsArray, Float16Array); // for optimization if (Constructor === Float16Array) { const proxy = new Float16Array(length); const array = getFloat16BitsArray(proxy); for (let i = 0; i < length; ++i) { const val = convertToNumber(float16bitsArray[i]); array[i] = roundToFloat16Bits( ReflectApply(callback, thisArg, [val, i, this]) ); } return proxy; } const array = new Constructor(length); assertSpeciesTypedArray(array, length); for (let i = 0; i < length; ++i) { const val = convertToNumber(float16bitsArray[i]); array[i] = ReflectApply(callback, thisArg, [val, i, this]); } return /** @type {any} */ (array); } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter */ filter(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; const kept = []; for (let i = 0; i < length; ++i) { const val = convertToNumber(float16bitsArray[i]); if (ReflectApply(callback, thisArg, [val, i, this])) { ArrayPrototypePush(kept, val); } } const Constructor = SpeciesConstructor(float16bitsArray, Float16Array); const array = new Constructor(kept); assertSpeciesTypedArray(array); return /** @type {any} */ (array); } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce */ reduce(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); if (length === 0 && opts.length === 0) { throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE); } let accumulator, start; if (opts.length === 0) { accumulator = convertToNumber(float16bitsArray[0]); start = 1; } else { accumulator = opts[0]; start = 0; } for (let i = start; i < length; ++i) { accumulator = callback( accumulator, convertToNumber(float16bitsArray[i]), i, this ); } return accumulator; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright */ reduceRight(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); if (length === 0 && opts.length === 0) { throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE); } let accumulator, start; if (opts.length === 0) { accumulator = convertToNumber(float16bitsArray[length - 1]); start = length - 2; } else { accumulator = opts[0]; start = length - 1; } for (let i = start; i >= 0; --i) { accumulator = callback( accumulator, convertToNumber(float16bitsArray[i]), i, this ); } return accumulator; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach */ forEach(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = 0; i < length; ++i) { ReflectApply(callback, thisArg, [ convertToNumber(float16bitsArray[i]), i, this, ]); } } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.find */ find(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = 0; i < length; ++i) { const value = convertToNumber(float16bitsArray[i]); if (ReflectApply(callback, thisArg, [value, i, this])) { return value; } } } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex */ findIndex(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = 0; i < length; ++i) { const value = convertToNumber(float16bitsArray[i]); if (ReflectApply(callback, thisArg, [value, i, this])) { return i; } } return -1; } /** @see https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlast */ findLast(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = length - 1; i >= 0; --i) { const value = convertToNumber(float16bitsArray[i]); if (ReflectApply(callback, thisArg, [value, i, this])) { return value; } } } /** @see https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlastindex */ findLastIndex(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = length - 1; i >= 0; --i) { const value = convertToNumber(float16bitsArray[i]); if (ReflectApply(callback, thisArg, [value, i, this])) { return i; } } return -1; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.every */ every(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = 0; i < length; ++i) { if ( !ReflectApply(callback, thisArg, [ convertToNumber(float16bitsArray[i]), i, this, ]) ) { return false; } } return true; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.some */ some(callback, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const length = TypedArrayPrototypeGetLength(float16bitsArray); const thisArg = opts[0]; for (let i = 0; i < length; ++i) { if ( ReflectApply(callback, thisArg, [ convertToNumber(float16bitsArray[i]), i, this, ]) ) { return true; } } return false; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.set */ set(input, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const targetOffset = ToIntegerOrInfinity(opts[0]); if (targetOffset < 0) { throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS); } if (input == null) { throw NativeTypeError( CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT ); } if (isNativeBigIntTypedArray(input)) { throw NativeTypeError( CANNOT_MIX_BIGINT_AND_OTHER_TYPES ); } // for optimization if (isFloat16Array(input)) { // peel off Proxy return TypedArrayPrototypeSet( getFloat16BitsArray(this), getFloat16BitsArray(input), targetOffset ); } if (isNativeTypedArray(input)) { const buffer = TypedArrayPrototypeGetBuffer(input); if (IsDetachedBuffer(buffer)) { throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER); } } const targetLength = TypedArrayPrototypeGetLength(float16bitsArray); const src = NativeObject(input); const srcLength = ToLength(src.length); if (targetOffset === Infinity || srcLength + targetOffset > targetLength) { throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS); } for (let i = 0; i < srcLength; ++i) { float16bitsArray[i + targetOffset] = roundToFloat16Bits(src[i]); } } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse */ reverse() { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); TypedArrayPrototypeReverse(float16bitsArray); return this; } /** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed */ toReversed() { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); // don't use SpeciesConstructor const uint16 = new NativeUint16Array( TypedArrayPrototypeGetBuffer(float16bitsArray), TypedArrayPrototypeGetByteOffset(float16bitsArray), TypedArrayPrototypeGetLength(float16bitsArray) ); const cloned = new Float16Array( TypedArrayPrototypeGetBuffer( TypedArrayPrototypeSlice(uint16) ) ); const clonedFloat16bitsArray = getFloat16BitsArray(cloned); TypedArrayPrototypeReverse(clonedFloat16bitsArray); return cloned; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill */ fill(value, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); TypedArrayPrototypeFill( float16bitsArray, roundToFloat16Bits(value), ...safeIfNeeded(opts) ); return this; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin */ copyWithin(target, start, ...opts) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); TypedArrayPrototypeCopyWithin(float16bitsArray, target, start, ...safeIfNeeded(opts)); return this; } /** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort */ sort(compareFn) { assertFloat16Array(this); const float16bitsArray = getFloat16BitsArray(this); const sortCompare = compareFn !== undefined ? compareFn : defaultCompare; TypedArrayPrototypeSort(float16bitsArray, (x, y) => { return sortCompare(convertToNumber(x), convertToNumber(y)); }); return this; } /** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSorted */ toSorted(compareFn) { assertFloat16Array(this); const float16bitsArray = ge