Files
completion-viz/engine262/src/abstract-ops/integer-indexed-objects.mjs
T

315 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { surroundingAgent } from '../engine.mjs';
import { Value, Type, Descriptor } from '../value.mjs';
import { Q, X } from '../completion.mjs';
import {
Assert,
CanonicalNumericIndexString,
IsAccessorDescriptor,
IsDetachedBuffer,
IsPropertyKey,
IsValidIntegerIndex,
MakeBasicObject,
OrdinaryGetOwnProperty,
OrdinaryHasProperty,
OrdinaryDefineOwnProperty,
OrdinaryGet,
OrdinarySet,
GetValueFromBuffer,
SetValueInBuffer,
ToString,
ToNumber,
ToBigInt,
isIntegerIndex,
typedArrayInfoByName,
} from './all.mjs';
export function isIntegerIndexedExoticObject(O) {
return O.GetOwnProperty === IntegerIndexedGetOwnProperty;
}
// 9.4.5.1 #sec-integer-indexed-exotic-objects-getownproperty-p
export function IntegerIndexedGetOwnProperty(P) {
const O = this;
// 1. Assert: IsPropertyKey(P) is true.
Assert(IsPropertyKey(P));
// 2. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 3. If Type(P) is String, then
if (Type(P) === 'String') {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
const numericIndex = X(CanonicalNumericIndexString(P));
// b. If numericIndex is not undefined, then
if (numericIndex !== Value.undefined) {
// i. Let value be ? IntegerIndexedElementGet(O, numericIndex).
const value = Q(IntegerIndexedElementGet(O, numericIndex));
// ii. If value is undefined, return undefined.
if (value === Value.undefined) {
return Value.undefined;
}
// iii. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }.
return Descriptor({
Value: value,
Writable: Value.true,
Enumerable: Value.true,
Configurable: Value.false,
});
}
}
// 4. Return OrdinaryGetOwnProperty(O, P).
return OrdinaryGetOwnProperty(O, P);
}
// 9.4.5.2 #sec-integer-indexed-exotic-objects-hasproperty-p
export function IntegerIndexedHasProperty(P) {
const O = this;
// 1. Assert: IsPropertyKey(P) is true.
Assert(IsPropertyKey(P));
// 2. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 3. If Type(P) is String, then
if (Type(P) === 'String') {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
const numericIndex = X(CanonicalNumericIndexString(P));
// b. If numericIndex is not undefined, then
if (numericIndex !== Value.undefined) {
// i. Let buffer be O.[[ViewedArrayBuffer]].
const buffer = O.ViewedArrayBuffer;
// ii. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (IsDetachedBuffer(buffer) === Value.true) {
return surroundingAgent.Throw('TypeError', 'ArrayBufferDetached');
}
// iii. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
if (IsValidIntegerIndex(O, numericIndex) === Value.false) {
return Value.false;
}
// iv. Return true.
return Value.true;
}
}
// 4. Return ? OrdinaryHasProperty(O, P)
return Q(OrdinaryHasProperty(O, P));
}
// #sec-integer-indexed-exotic-objects-defineownproperty-p-desc
export function IntegerIndexedDefineOwnProperty(P, Desc) {
const O = this;
// 1. Assert: IsPropertyKey(P) is true.
Assert(IsPropertyKey(P));
// 2. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 3. If Type(P) is String, then
if (Type(P) === 'String') {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
const numericIndex = X(CanonicalNumericIndexString(P));
// b. If numericIndex is not undefined, then
if (numericIndex !== Value.undefined) {
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
if (IsValidIntegerIndex(O, numericIndex) === Value.false) {
return Value.false;
}
// ii. If IsAccessorDescriptor(Desc) is true, return false.
if (IsAccessorDescriptor(Desc)) {
return Value.false;
}
// iii. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is true, return false.
if (Desc.Configurable === Value.true) {
return Value.false;
}
// iv. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
if (Desc.Enumerable === Value.false) {
return Value.false;
}
// v. If Desc has a [[Writable]] field and if Desc.[[Writable]] is false, return false.
if (Desc.Writable === Value.false) {
return Value.false;
}
// vi. If Desc has a [[Value]] field, then
if (Desc.Value !== undefined) {
// 1. Let value be Desc.[[Value]].
const value = Desc.Value;
// 2. Return ? IntegerIndexedElementSet(O, numericIndex, value).
return Q(IntegerIndexedElementSet(O, numericIndex, value));
}
// vii. Return true.
return Value.true;
}
}
// 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
return Q(OrdinaryDefineOwnProperty(O, P, Desc));
}
// 9.4.5.4 #sec-integer-indexed-exotic-objects-get-p-receiver
export function IntegerIndexedGet(P, Receiver) {
const O = this;
// 1. Assert: IsPropertykey(P) is true.
Assert(IsPropertyKey(P));
// 2. If Type(P) is String, then
if (Type(P) === 'String') {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
const numericIndex = X(CanonicalNumericIndexString(P));
// b. If numericIndex is not undefined, then
if (numericIndex !== Value.undefined) {
// i. Return ? IntegerIndexedElementGet(O, numericIndex).
return Q(IntegerIndexedElementGet(O, numericIndex));
}
}
// 3. Return ? OrdinaryGet(O, P, Receiver).
return Q(OrdinaryGet(O, P, Receiver));
}
// 9.4.5.5 #sec-integer-indexed-exotic-objects-set-p-v-receiver
export function IntegerIndexedSet(P, V, Receiver) {
const O = this;
// 1. Assert: IsPropertyKey(P) is true.
Assert(IsPropertyKey(P));
// 2. If Type(P) is String, then
if (Type(P) === 'String') {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
const numericIndex = X(CanonicalNumericIndexString(P));
// b. If numericIndex is not undefined, then
if (numericIndex !== Value.undefined) {
// i. Return ? IntegerIndexedElementSet(O, numericIndex, V).
return Q(IntegerIndexedElementSet(O, numericIndex, V));
}
}
// 3. Return ? OrdinarySet(O, P, V, Receiver).
return Q(OrdinarySet(O, P, V, Receiver));
}
// 9.4.5.6 #sec-integer-indexed-exotic-objects-ownpropertykeys
export function IntegerIndexedOwnPropertyKeys() {
const O = this;
// 1. Let keys be a new empty List.
const keys = [];
// 2. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 3. Let len be O.[[ArrayLength]].
const len = O.ArrayLength.numberValue();
// 4. For each integer i starting with 0 such that i < len, in ascending order, do
for (let i = 0; i < len; i += 1) {
// a. Add ! ToString(i) as the last element of keys.
keys.push(X(ToString(new Value(i))));
}
// 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in ascending chronological order of property creation, do
for (const P of O.properties.keys()) {
if (Type(P) === 'String') {
if (!isIntegerIndex(P)) {
// a. Add P as the last element of keys.
keys.push(P);
}
}
}
// 6. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
for (const P of O.properties.keys()) {
if (Type(P) === 'Symbol') {
// a. Add P as the last element of keys.
keys.push(P);
}
}
// 7. Return keys.
return keys;
}
// #sec-integerindexedelementget
export function IntegerIndexedElementGet(O, index) {
// 1. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 2. Assert: Type(index) is Number.
Assert(Type(index) === 'Number');
// 3. Let buffer be O.[[ViewedArrayBuffer]].
const buffer = O.ViewedArrayBuffer;
// 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (IsDetachedBuffer(buffer) === Value.true) {
return surroundingAgent.Throw('TypeError', 'ArrayBufferDetached');
}
// 5. If ! IsValidIntegerIndex(O, index) is false, return undefined.
if (IsValidIntegerIndex(O, index) === Value.false) {
return Value.undefined;
}
// 6. Let offset be O.[[ByteOffset]].
const offset = O.ByteOffset;
// 7. Let arrayTypeName be the String value of O.[[TypedArrayName]].
const arrayTypeName = O.TypedArrayName.stringValue();
// 8. Let elementSize be the Element Size value specified in Table 61 for arrayTypeName.
const elementSize = typedArrayInfoByName[arrayTypeName].ElementSize;
// 9. Let indexedPosition be (index × elementSize) + offset.
const indexedPosition = new Value((index.numberValue() * elementSize) + offset.numberValue());
// 10. Let elementType be the Element Type value in Table 61 for arrayTypeName.
const elementType = typedArrayInfoByName[arrayTypeName].ElementType;
// 11. Return GetValueFromBuffer(buffer, indexedPosition, elementType, true, Unordered).
return GetValueFromBuffer(buffer, indexedPosition, elementType, Value.true, 'Unordered');
}
// #sec-integerindexedelementset
export function IntegerIndexedElementSet(O, index, value) {
// 1. Assert: O is an Integer-Indexed exotic object.
Assert(isIntegerIndexedExoticObject(O));
// 2. Assert: Type(index) is Number.
Assert(Type(index) === 'Number');
// 3. If O.[[ContentType]] is BigInt, let numValue be ? ToBigInt(value).
// 4. Otherwise, let numValue be ? ToNumber(value).
let numValue;
if (O.ContentType === 'BigInt') {
numValue = Q(ToBigInt(value));
} else {
numValue = Q(ToNumber(value));
}
// 5. Let buffer be O.[[ViewedArrayBuffer]].
const buffer = O.ViewedArrayBuffer;
// 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (IsDetachedBuffer(buffer) === Value.true) {
return surroundingAgent.Throw('TypeError', 'ArrayBufferDetached');
}
// 7. If ! IsValidIntegerIndex(O, index) is false, return false.
if (IsValidIntegerIndex(O, index) === Value.false) {
return Value.false;
}
// 8. Let offset be O.[[ByteOffset]].
const offset = O.ByteOffset;
// 9. Let arrayTypeName be the String value of O.[[TypedArrayName]].
const arrayTypeName = O.TypedArrayName.stringValue();
// 10. Let elementSize be the Element Size value specified in Table 61 for arrayTypeName.
const elementSize = typedArrayInfoByName[arrayTypeName].ElementSize;
// 11. Let indexedPosition be (index × elementSize) + offset.
const indexedPosition = new Value((index.numberValue() * elementSize) + offset.numberValue());
// 12. Let elementType be the Element Type value in Table 61 for arrayTypeName.
const elementType = typedArrayInfoByName[arrayTypeName].ElementType;
// 13. Perform SetValueInBuffer(buffer, indexedPosition, elementType, numValue, true, Unordered).
X(SetValueInBuffer(buffer, indexedPosition, elementType, numValue, Value.true, 'Unordered'));
// 14. Return true.
return Value.true;
}
// #sec-integerindexedobjectcreate
export function IntegerIndexedObjectCreate(prototype) {
// 1. Let internalSlotsList be « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] ».
const internalSlotsList = [
'Prototype',
'Extensible',
'ViewedArrayBuffer',
'TypedArrayName',
'ContentType',
'ByteLength',
'ByteOffset',
'ArrayLength',
];
// 2. Let A be ! MakeBasicObject(internalSlotsList).
const A = X(MakeBasicObject(internalSlotsList));
// 3. Set A.[[GetOwnProperty]] as specified in 9.4.5.1.
A.GetOwnProperty = IntegerIndexedGetOwnProperty;
// 4. Set A.[[HasProperty]] as specified in 9.4.5.2.
A.HasProperty = IntegerIndexedHasProperty;
// 5. Set A.[[DefineOwnProperty]] as specified in 9.4.5.3.
A.DefineOwnProperty = IntegerIndexedDefineOwnProperty;
// 6. Set A.[[Get]] as specified in 9.4.5.4.
A.Get = IntegerIndexedGet;
// 7. Set A.[[Set]] as specified in 9.4.5.5.
A.Set = IntegerIndexedSet;
// 8. Set A.[[OwnPropertyKeys]] as specified in 9.4.5.6.
A.OwnPropertyKeys = IntegerIndexedOwnPropertyKeys;
// 9. Set A.[[Prototype]] to prototype.
A.Prototype = prototype;
// 10. Return A.
return A;
}