mirror of
https://github.com/bendtherules/completion-viz.git
synced 2026-08-18 21:52:36 +00:00
315 lines
12 KiB
JavaScript
315 lines
12 KiB
JavaScript
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;
|
||
}
|