UNPKG

linvail

Version:

Provenancial Equality for JavaScript

1,566 lines (1,563 loc) 50.1 kB
import { clamp, incrementWhenNegative, toInteger } from "../../util/number.mjs"; import { hasOwnNarrow } from "../../util/record.mjs"; import { atExternal, atInternal, createSpecieArray, toInternalClosureSloppy, toInternalClosureStrict, toInternalReferenceSloppy, toInternalReferenceStrict, isConcatSpreadable, getLength, convertArrayLike, convertIterator, flatenArray, sortInternalValueArray, void_oracle, } from "./helper.mjs"; import { applyInternal, defineInternalPropertyDescriptor, deleteInternalOwnProperty, getInternalPropertyValue, hasInternalProperty, isInternalArray, setInternalPropertyValue, } from "../reflect.mjs"; import { wrapStandardPrimitive } from "../region/core.mjs"; import { createEmptyArray, createFullArray } from "../region/create.mjs"; const { Math: { max, min, floor }, } = globalThis; /** * @type {Record< * ( * | "global.Array" * | `global.Array.${Exclude<keyof typeof Array, symbol>}` * | `global.Array.prototype.${Exclude<keyof typeof Array.prototype, symbol>}` * ), * import("../oracle.d.ts").Oracle * >} */ export const array_oracle_record = { "global.Array": { construct: (region, input, new_target) => { const { "global.Reflect.setPrototypeOf": setPrototypeOf } = region; const argument0 = atExternal(region, input, 0); /** @type {import("../domain.d.ts").HostReferenceWrapper<"array">} */ let result; /* BREAKAGE: we should use array_prototype from new_target's realm */ if (input.length === 1 && typeof argument0 === "number") { const length = toInteger(argument0, 0); if (argument0 !== length) { throw new region["global.RangeError"]( "Invalid array length at Array", ); } result = createEmptyArray(region, length); } else { result = createFullArray(region, input); } const prototype = getInternalPropertyValue( region, new_target, "prototype", new_target, ); if (prototype.type !== "primitive") { if (!setPrototypeOf(result.plain, prototype.inner)) { throw new region["global.TypeError"]("Cannot set prototype of array"); } } return result; }, apply: (region, _that, input) => { const { "global.RangeError": RangeError } = region; const argument0 = atExternal(region, input, 0); if (input.length === 1 && typeof argument0 === "number") { const length = toInteger(argument0, 0); if (argument0 !== length) { throw new RangeError("Invalid array length at Array"); } return createEmptyArray(region, length); } else { return createFullArray(region, input); } }, }, "global.Array.from": { construct: null, apply: (region, _that, input) => { const { "global.TypeError": TypeError, "global.Symbol.iterator": iterator_symbol, "global.Array.prototype[@@iterator]": array_iterator, "global.Object.is": is, } = region; const target = toInternalReferenceSloppy( region, atInternal(region, input, 0), ); const transform = toInternalClosureSloppy( region, atInternal(region, input, 1), ); const this_arg = atInternal(region, input, 2); const generate = getInternalPropertyValue( region, target, iterator_symbol, target, ); if (generate.type === "primitive") { if (generate.inner == null) { return convertArrayLike(region, target, transform, this_arg); } else { throw new TypeError("@@iterator is not a function at Array.from"); } } else { if (is(generate.inner, array_iterator)) { return convertArrayLike(region, target, transform, this_arg); } else { return convertIterator( region, toInternalReferenceStrict( region, applyInternal(region, generate, target, []), ), transform, this_arg, ); } } }, }, "global.Array.isArray": void_oracle, // no benefit, "global.Array.of": { construct: null, apply: (region, _that, input) => createFullArray(region, input), }, "global.Array.prototype": void_oracle, // not a function "global.Array.prototype.at": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined, "global.Number": Number } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); const index = incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), length, ); if (index < 0 || index >= length) { return wrapStandardPrimitive(region, undefined); } else { return getInternalPropertyValue(region, target, index, target); } }, }, "global.Array.prototype.concat": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number.MAX_SAFE_INTEGER": MAX_SAFE_INTEGER, } = region; const target = toInternalReferenceSloppy(region, that); const result = createSpecieArray(region, target, 0); let result_length = 0; const input_length = input.length; for (let index = -1; index < input_length; index++) { const current = index === -1 ? target : input[index]; if ( (current.type === "host" || current.type === "guest") && isConcatSpreadable(region, current) ) { const current_length = getLength(region, current); if (result_length + current_length >= MAX_SAFE_INTEGER) { throw new TypeError( "Array length exceeds maximum safe integer at Array.prototype.concat", ); } for (let index = 0; index < current_length; index++) { if (hasInternalProperty(region, current, index)) { if ( !defineInternalPropertyDescriptor( region, result, result_length, { __proto__: null, value: getInternalPropertyValue( region, current, index, current, ), writable: true, enumerable: true, configurable: true, }, ) ) { throw new TypeError( "Cannot define array index at Array.prototype.concat", ); } } else { if ( !defineInternalPropertyDescriptor(region, result, "length", { __proto__: null, value: wrapStandardPrimitive(region, result_length + 1), writable: true, enumerable: false, configurable: false, }) ) { throw new TypeError( "Cannot define array length at Array.prototype.concat", ); } } result_length++; } } else { if (result_length >= MAX_SAFE_INTEGER) { throw new TypeError( "Array length exceeds maximum safe integer at Array.prototype.concat", ); } if ( !defineInternalPropertyDescriptor(region, result, result_length, { __proto__: null, value: current, writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.concat", ); } result_length++; } } return result; }, }, "global.Array.prototype.copyWithin": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number": Number, "global.undefined": undefined, } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); const index1 = max( 0, incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), length, ), ); const index2 = max( 0, incrementWhenNegative( toInteger(Number(atExternal(region, input, 1)), 0), length, ), ); const argument2 = atExternal(region, input, 2); const index3 = min( length, argument2 === undefined ? length : incrementWhenNegative(toInteger(Number(argument2), 0), length), ); let count = index3 - index2; if (count + index1 > length) { count = length - index1; } const direction = index1 <= index2 ? 1 : -1; let target_index = direction > 0 ? index1 : index1 + count - 1; let source_index = direction > 0 ? index2 : index2 + count - 1; for (let index = 0; index < count; index++) { if (hasInternalProperty(region, target, source_index)) { if ( !setInternalPropertyValue( region, target, target_index, getInternalPropertyValue(region, target, source_index, target), target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.copyWithin", ); } } else { if (!deleteInternalOwnProperty(region, target, target_index)) { throw new TypeError( "Cannot delete array index at Array.prototype.copyWithin", ); } } target_index += direction; source_index += direction; } return target; }, }, "global.Array.prototype.entries": void_oracle, // returns exotic array iterator object "global.Array.prototype.every": { construct: null, apply: (region, that, input) => { const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = 0; index < length; index++) { if (hasInternalProperty(region, target, index)) { if ( !applyInternal(region, predicate, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]).inner ) { return wrapStandardPrimitive(region, false); } } } return wrapStandardPrimitive(region, true); }, }, "global.Array.prototype.fill": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number": Number, "global.undefined": undefined, } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); const value = atInternal(region, input, 0); const index1 = max( 0, incrementWhenNegative( toInteger(Number(atExternal(region, input, 1)), 0), length, ), ); const argument2 = atExternal(region, input, 2); const index2 = argument2 === undefined ? length : min( length, incrementWhenNegative(toInteger(Number(argument2), 0), length), ); for (let index = index1; index < index2; index++) { if (!setInternalPropertyValue(region, target, index, value, target)) { throw new TypeError("Cannot set array index at Array.prototype.fill"); } } return target; }, }, "global.Array.prototype.filter": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const target_length = getLength(region, target); const result = createSpecieArray(region, target, 0); let arg_index = 0; let res_index = 0; while (arg_index < target_length) { if (hasInternalProperty(region, target, arg_index)) { const item = getInternalPropertyValue( region, target, arg_index, target, ); if ( applyInternal(region, predicate, this_arg, [ item, wrapStandardPrimitive(region, arg_index), target, ]).inner ) { if ( !defineInternalPropertyDescriptor(region, result, res_index, { __proto__: null, value: item, writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.filter", ); } res_index++; } } arg_index++; } if ( !defineInternalPropertyDescriptor(region, result, "length", { __proto__: null, value: wrapStandardPrimitive(region, res_index), writable: true, enumerable: false, configurable: false, }) ) { throw new TypeError( "Cannot define array length at Array.prototype.filter", ); } return result; }, }, "global.Array.prototype.find": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined } = region; const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = 0; index < length; index++) { const value = getInternalPropertyValue(region, target, index, target); if ( applyInternal(region, predicate, this_arg, [ value, wrapStandardPrimitive(region, index), target, ]).inner ) { return value; } } return wrapStandardPrimitive(region, undefined); }, }, "global.Array.prototype.findIndex": { construct: null, apply: (region, that, input) => { const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = 0; index < length; index++) { if ( applyInternal(region, predicate, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]).inner ) { return wrapStandardPrimitive(region, index); } } return wrapStandardPrimitive(region, -1); }, }, "global.Array.prototype.findLast": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined } = region; const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = length - 1; index >= 0; index--) { const value = getInternalPropertyValue(region, target, index, target); if ( applyInternal(region, predicate, this_arg, [ value, wrapStandardPrimitive(region, index), target, ]).inner ) { return value; } } return wrapStandardPrimitive(region, undefined); }, }, "global.Array.prototype.findLastIndex": { construct: null, apply: (region, that, input) => { const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = length - 1; index >= 0; index--) { if ( applyInternal(region, predicate, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]).inner ) { return wrapStandardPrimitive(region, index); } } return wrapStandardPrimitive(region, -1); }, }, "global.Array.prototype.flat": { construct: null, apply: (region, that, input) => { const { "global.Number": Number } = region; const target = toInternalReferenceSloppy(region, that); const argument0 = atExternal(region, input, 0); const depth = argument0 == null ? 1 : max(0, toInteger(Number(argument0), 0)); const result = createSpecieArray(region, target, 0); defineInternalPropertyDescriptor(region, result, "length", { __proto__: null, value: wrapStandardPrimitive( region, flatenArray(region, depth + 1, target, result, 0), ), writable: true, enumerable: false, configurable: false, }); return result; }, }, "global.Array.prototype.flatMap": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const transform = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const target_length = getLength(region, target); const result = createSpecieArray(region, target, 0); let result_length = 0; for (let index = 0; index < target_length; index++) { if (hasInternalProperty(region, target, index)) { const item = applyInternal(region, transform, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]); if (isInternalArray(region, item)) { const item_length = getLength(region, item); for (let index = 0; index < item_length; index++) { if (hasInternalProperty(region, item, index)) { if ( !defineInternalPropertyDescriptor( region, result, result_length, { __proto__: null, value: getInternalPropertyValue( region, item, index, item, ), writable: true, enumerable: true, configurable: true, }, ) ) { throw new TypeError( "Cannot define array index at Array.prototype.flatMap", ); } result_length++; } } } else { if ( !defineInternalPropertyDescriptor(region, result, result_length, { __proto__: null, value: item, writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.map", ); } result_length++; } } } return result; }, }, "global.Array.prototype.forEach": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined } = region; const target = toInternalReferenceSloppy(region, that); const callback = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = 0; index < length; index++) { if (hasInternalProperty(region, target, index)) { applyInternal(region, callback, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]); } } return wrapStandardPrimitive(region, undefined); }, }, "global.Array.prototype.includes": void_oracle, // no benefit "global.Array.prototype.indexOf": void_oracle, // no benefit "global.Array.prototype.join": void_oracle, // no benefit "global.Array.prototype.keys": void_oracle, // returns exotic array iterator object "global.Array.prototype.lastIndexOf": void_oracle, // no benefit "global.Array.prototype.length": void_oracle, // not a function "global.Array.prototype.map": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const transform = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const target_length = getLength(region, target); const result = createSpecieArray(region, target, target_length); for (let index = 0; index < target_length; index++) { if (hasInternalProperty(region, target, index)) { if ( !defineInternalPropertyDescriptor(region, result, index, { __proto__: null, value: applyInternal(region, transform, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.map", ); } } } return result; }, }, "global.Array.prototype.pop": { construct: null, apply: (region, that, _input) => { const { "global.undefined": undefined, "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); if (length === 0) { if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, 0), target, ) ) { throw new TypeError("Cannot set array length at Array.prototype.pop"); } return wrapStandardPrimitive(region, undefined); } else { const value = getInternalPropertyValue( region, target, length - 1, target, ); if (!deleteInternalOwnProperty(region, target, length - 1)) { throw new TypeError( "Cannot delete array index at Array.prototype.pop", ); } if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, length - 1), target, ) ) { throw new TypeError("Cannot set array length at Array.prototype.pop"); } return value; } }, }, "global.Array.prototype.push": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number.MAX_SAFE_INTEGER": MAX_SAFE_INTEGER, } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); for (let index = 0; index < input.length; index++) { if (length >= MAX_SAFE_INTEGER - index) { throw new TypeError( "Array length exceeds maximum safe integer at Array.prototype.push", ); } if ( !setInternalPropertyValue( region, target, length + index, input[index], target, ) ) { throw new TypeError("Cannot set array index at Array.prototype.push"); } } if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, length + input.length), target, ) ) { throw new TypeError("Cannot set array length at Array.prototype.push"); } return wrapStandardPrimitive(region, length + input.length); }, }, "global.Array.prototype.reduce": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const accumulate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const initial_value = atInternal(region, input, 1); const this_arg = atInternal(region, input, 2); const length = getLength(region, target); let initialized = input.length > 1; let accumulation = initial_value; for (let index = 0; index < length; index++) { if (hasInternalProperty(region, target, index)) { const item = getInternalPropertyValue(region, target, index, target); if (!initialized) { accumulation = item; initialized = true; } else { accumulation = applyInternal(region, accumulate, this_arg, [ accumulation, item, wrapStandardPrimitive(region, index), target, ]); } } } if (!initialized) { throw new TypeError("Missing initial value at Array.prototype.reduce"); } return accumulation; }, }, "global.Array.prototype.reduceRight": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const accumulate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const initial_value = atInternal(region, input, 1); const this_arg = atInternal(region, input, 2); const length = getLength(region, target); let initialized = input.length > 1; let accumulation = initial_value; for (let index = length - 1; index >= 0; index--) { if (hasInternalProperty(region, target, index)) { const item = getInternalPropertyValue(region, target, index, target); if (!initialized) { accumulation = item; initialized = true; } else { accumulation = applyInternal(region, accumulate, this_arg, [ accumulation, item, wrapStandardPrimitive(region, index), target, ]); } } } if (!initialized) { throw new TypeError("Missing initial value at Array.prototype.reduce"); } return accumulation; }, }, "global.Array.prototype.reverse": { construct: null, apply: (region, that, _input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); const middle = floor(length / 2); for (let index = 0; index < middle; index++) { const lower_index = index; const upper_index = length - index - 1; const lower_value = hasInternalProperty(region, target, lower_index) ? { inner: getInternalPropertyValue( region, target, lower_index, target, ), } : {}; const upper_value = hasInternalProperty(region, target, upper_index) ? { inner: getInternalPropertyValue( region, target, upper_index, target, ), } : {}; if (hasOwnNarrow(upper_value, "inner")) { if ( !setInternalPropertyValue( region, target, lower_index, upper_value.inner, target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.reverse", ); } } else { if (!deleteInternalOwnProperty(region, target, lower_index)) { throw new TypeError( "Cannot delete array index at Array.prototype.reverse", ); } } if (hasOwnNarrow(lower_value, "inner")) { if ( !setInternalPropertyValue( region, target, upper_index, lower_value.inner, target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.reverse", ); } } else { if (!deleteInternalOwnProperty(region, target, upper_index)) { throw new TypeError( "Cannot delete array index at Array.prototype.reverse", ); } } } return target; }, }, "global.Array.prototype.shift": { construct: null, apply: (region, that, _input) => { const { "global.undefined": undefined, "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); if (length === 0) { if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, 0), target, ) ) { throw new TypeError( "Cannot set array length at Array.prototype.shift", ); } return wrapStandardPrimitive(region, undefined); } const initial = getInternalPropertyValue(region, target, 0, target); for (let index = 0; index < length; index++) { if (hasInternalProperty(region, target, index + 1)) { if ( !setInternalPropertyValue( region, target, index, getInternalPropertyValue(region, target, index + 1, target), target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.shift", ); } } else { if (!deleteInternalOwnProperty(region, target, index)) { throw new TypeError( "Cannot delete array index at Array.prototype.shift", ); } } } if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, length - 1), target, ) ) { throw new TypeError( "Cannot define array length at Array.prototype.shift", ); } return initial; }, }, "global.Array.prototype.slice": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number": Number, "global.undefined": undefined, } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const index1 = max( 0, incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), target_length, ), ); const argument1 = atExternal(region, input, 1); const index2 = argument1 === undefined ? target_length : min( target_length, incrementWhenNegative( toInteger(Number(atExternal(region, input, 1)), 0), target_length, ), ); const result = createSpecieArray(region, target, max(index2 - index1, 0)); for (let index = index1; index < index2; index++) { if ( !defineInternalPropertyDescriptor(region, result, index - index1, { __proto__: null, value: getInternalPropertyValue(region, target, index, target), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.slice", ); } } return result; }, }, "global.Array.prototype.some": { construct: null, apply: (region, that, input) => { const target = toInternalReferenceSloppy(region, that); const predicate = toInternalClosureStrict( region, atInternal(region, input, 0), ); const this_arg = atInternal(region, input, 1); const length = getLength(region, target); for (let index = 0; index < length; index++) { if (hasInternalProperty(region, target, index)) { if ( applyInternal(region, predicate, this_arg, [ getInternalPropertyValue(region, target, index, target), wrapStandardPrimitive(region, index), target, ]).inner ) { return wrapStandardPrimitive(region, true); } } } return wrapStandardPrimitive(region, false); }, }, "global.Array.prototype.sort": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined, "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const argument0 = atInternal(region, input, 0); let compare = null; if (argument0.type === "primitive") { if (argument0.inner !== undefined) { throw new TypeError( "Invalid compare function at Array.prototype.sort", ); } } else { if (typeof argument0.inner !== "function") { throw new TypeError( "Invalid compare function at Array.prototype.sort", ); } compare = argument0; } const copy = sortInternalValueArray( region, target, target_length, compare, "skip", ); const copy_length = copy.length; for (let index = 0; index < target_length; index++) { if (index < copy_length) { if ( !setInternalPropertyValue( region, target, index, copy[index], target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.sort", ); } } else { if (!deleteInternalOwnProperty(region, target, index)) { throw new TypeError( "Cannot delete array index at Array.prototype.sort", ); } } } return target; }, }, "global.Array.prototype.splice": { construct: null, apply: (region, that, input) => { const { "global.Number": Number, "global.TypeError": TypeError, "global.Number.MAX_SAFE_INTEGER": MAX_SAFE_INTEGER, } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const start_index = clamp( incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), target_length, ), 0, target_length, ); const delete_count = input.length === 1 ? target_length - start_index : clamp( toInteger(Number(atExternal(region, input, 1)), 0), 0, target_length - start_index, ); const item_count = max(0, input.length - 2); if (target_length + item_count - delete_count > MAX_SAFE_INTEGER) { throw new TypeError( "Array length exceeds maximum safe integer at Array.prototype.splice", ); } const result = createSpecieArray(region, target, delete_count); for (let result_index = 0; result_index < delete_count; result_index++) { const target_index = start_index + result_index; if (hasInternalProperty(region, target, target_index)) { if ( !defineInternalPropertyDescriptor(region, result, result_index, { __proto__: null, value: getInternalPropertyValue( region, target, target_index, target, ), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.splice", ); } } } if ( !setInternalPropertyValue( region, result, "length", wrapStandardPrimitive(region, delete_count), result, ) ) { throw new TypeError( "Cannot set array length at Array.prototype.splice", ); } if (item_count < delete_count) { for ( let index = start_index; index < target_length - delete_count; index++ ) { if (hasInternalProperty(region, target, index + delete_count)) { if ( !setInternalPropertyValue( region, target, index + item_count, getInternalPropertyValue( region, target, index + delete_count, target, ), target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.splice", ); } } else { if ( !deleteInternalOwnProperty(region, target, index + item_count) ) { throw new TypeError( "Cannot delete array index at Array.prototype.splice", ); } } } for ( let index = target_length; index > target_length - delete_count + item_count; index-- ) { if (!deleteInternalOwnProperty(region, target, index - 1)) { throw new TypeError( "Cannot delete array index at Array.prototype.splice", ); } } } if (item_count > delete_count) { for ( let index = target_length - delete_count; index > start_index; index-- ) { if (hasInternalProperty(region, target, index + delete_count - 1)) { if ( !setInternalPropertyValue( region, target, index + item_count - 1, getInternalPropertyValue( region, target, index + delete_count - 1, target, ), target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.splice", ); } } else { if ( !deleteInternalOwnProperty(region, target, index + item_count - 1) ) { throw new TypeError( "Cannot delete array index at Array.prototype.splice", ); } } } } for (let index = 0; index < item_count; index++) { if ( !setInternalPropertyValue( region, target, start_index + index, input[index + 2], target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.splice", ); } } if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive( region, target_length - delete_count + item_count, ), target, ) ) { throw new TypeError( "Cannot set array length at Array.prototype.splice", ); } return result; }, }, "global.Array.prototype.toLocaleString": void_oracle, // no benefit "global.Array.prototype.toReversed": { construct: null, apply: (region, that, _input) => { const { "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const result = createEmptyArray(region, 0); for (let index = 0; index < target_length; index++) { if ( !defineInternalPropertyDescriptor(region, result, index, { __proto__: null, value: getInternalPropertyValue( region, target, target_length - index - 1, target, ), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.toReversed", ); } } return result; }, }, "global.Array.prototype.toSorted": { construct: null, apply: (region, that, input) => { const { "global.undefined": undefined, "global.TypeError": TypeError } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const argument0 = atInternal(region, input, 0); let compare = null; if (argument0.type === "primitive") { if (argument0.inner !== undefined) { throw new TypeError( "Invalid compare function at Array.prototype.sort", ); } } else { if (typeof argument0.inner !== "function") { throw new TypeError( "Invalid compare function at Array.prototype.sort", ); } compare = argument0; } return createFullArray( region, sortInternalValueArray(region, target, target_length, compare, "read"), ); }, }, "global.Array.prototype.toSpliced": { construct: null, apply: (region, that, input) => { const { "global.Number": Number, "global.TypeError": TypeError, "global.Reflect.defineProperty": defineProperty, } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const start_index = clamp( incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), target_length, ), 0, target_length, ); const delete_count = input.length === 1 ? target_length - start_index : clamp( toInteger(Number(atExternal(region, input, 1)), 0), 0, target_length - start_index, ); const item_count = max(0, input.length - 2); const result = createEmptyArray( region, target_length - delete_count + item_count, ); for (let index = 0; index < start_index; index++) { if ( !defineProperty(result.plain, index, { __proto__: null, value: getInternalPropertyValue(region, target, index, target), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.toSpliced", ); } } for (let index = start_index; index < start_index + item_count; index++) { if ( !defineProperty(result.plain, index, { __proto__: null, value: atInternal(region, input, index + 2 - start_index), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.toSpliced", ); } } for ( let index = start_index + item_count; index < target_length + item_count - delete_count; index++ ) { if ( !defineProperty(result.plain, index, { __proto__: null, value: getInternalPropertyValue( region, target, index + delete_count - item_count, target, ), writable: true, enumerable: true, configurable: true, }) ) { throw new TypeError( "Cannot define array index at Array.prototype.toSpliced", ); } } return result; }, }, "global.Array.prototype.toString": void_oracle, // no benefit "global.Array.prototype.unshift": { construct: null, apply: (region, that, input) => { const { "global.TypeError": TypeError, "global.Number.MAX_SAFE_INTEGER": MAX_SAFE_INTEGER, } = region; const target = toInternalReferenceSloppy(region, that); const target_length = getLength(region, target); const input_length = input.length; const new_length = target_length + input_length; if (new_length >= MAX_SAFE_INTEGER) { throw new TypeError( "Array length exceeds maximum safe integer at Array.prototype.unshift", ); } for (let index = target_length - 1; index >= 0; index--) { if (hasInternalProperty(region, target, index)) { if ( !setInternalPropertyValue( region, target, index + input.length, getInternalPropertyValue(region, target, index, target), target, ) ) { throw new TypeError( "Cannot set array index at Array.prototype.unshift", ); } } else { if ( !deleteInternalOwnProperty(region, target, index + input_length) ) { throw new TypeError( "Cannot delete array index at Array.prototype.unshift", ); } } } for (let index = 0; index < input_length; index++) { if ( !setInternalPropertyValue(region, target, index, input[index], target) ) { throw new TypeError( "Cannot set array index at Array.prototype.unshift", ); } } if ( !setInternalPropertyValue( region, target, "length", wrapStandardPrimitive(region, new_length), target, ) ) { throw new TypeError( "Cannot set array length at Array.prototype.unshift", ); } return wrapStandardPrimitive(region, new_length); }, }, "global.Array.prototype.values": void_oracle, // returns exotic array iterator object "global.Array.prototype.with": { construct: null, apply: (region, that, input) => { const { "global.Number": Number, "global.RangeError": RangeError, "global.TypeError": TypeError, } = region; const target = toInternalReferenceSloppy(region, that); const length = getLength(region, target); const match = incrementWhenNegative( toInteger(Number(atExternal(region, input, 0)), 0), length, ); const item = atInternal(region, input, 1); if (match < 0 || match >= length) { throw new RangeError( "Array index out of range at Array.prototype.with", ); } const result = createEmptyArray(region, length); for (let index = 0; index < length; index++) { if ( !setInternalPropertyValue( region, result, index, index === match ? item : getInternalPropertyValue(region, target, index, target), result, ) ) { throw new TypeError("Cannot set array index at Array.prototype.with"); } }