mirror of
https://github.com/bendtherules/completion-viz.git
synced 2026-08-18 13:42:51 +00:00
Clone engine262 in /engine262
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
import { surroundingAgent } from '../engine.mjs';
|
||||
import { Type, Value } from '../value.mjs';
|
||||
import { Q, X, NormalCompletion } from '../completion.mjs';
|
||||
import {
|
||||
Assert, OrdinaryCreateFromConstructor,
|
||||
IsNonNegativeInteger, CreateByteDataBlock,
|
||||
SameValue, IsConstructor, CopyDataBlockBytes,
|
||||
typedArrayInfoByType,
|
||||
} from './all.mjs';
|
||||
|
||||
// #sec-allocatearraybuffer
|
||||
export function AllocateArrayBuffer(constructor, byteLength) {
|
||||
// 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »).
|
||||
const obj = Q(OrdinaryCreateFromConstructor(constructor, '%ArrayBuffer.prototype%', [
|
||||
'ArrayBufferData', 'ArrayBufferByteLength', 'ArrayBufferDetachKey',
|
||||
]));
|
||||
// 2. Assert: ! IsNonNegativeInteger(byteLength) is true.
|
||||
Assert(X(IsNonNegativeInteger(byteLength)) === Value.true);
|
||||
// 3. Let block be ? CreateByteDataBlock(byteLength).
|
||||
const block = Q(CreateByteDataBlock(byteLength));
|
||||
// 4. Set obj.[[ArrayBufferData]] to block.
|
||||
obj.ArrayBufferData = block;
|
||||
// 5. Set obj.[[ArrayBufferByteLength]] to byteLength.
|
||||
obj.ArrayBufferByteLength = byteLength;
|
||||
// 6. Return obj.
|
||||
return obj;
|
||||
}
|
||||
|
||||
// #sec-isdetachedbuffer
|
||||
export function IsDetachedBuffer(arrayBuffer) {
|
||||
// 1. Assert: Type(arrayBuffer) is Object and it has an [[ArrayBufferData]] internal slot.
|
||||
Assert(Type(arrayBuffer) === 'Object' && 'ArrayBufferData' in arrayBuffer);
|
||||
// 2. If arrayBuffer.[[ArrayBufferData]] is null, return true.
|
||||
if (arrayBuffer.ArrayBufferData === Value.null) {
|
||||
return Value.true;
|
||||
}
|
||||
// 3. Return false.
|
||||
return Value.false;
|
||||
}
|
||||
|
||||
// #sec-detacharraybuffer
|
||||
export function DetachArrayBuffer(arrayBuffer, key) {
|
||||
// 1. Assert: Type(arrayBuffer) is Object and it has [[ArrayBufferData]], [[ArrayBufferByteLength]], and [[ArrayBufferDetachKey]] internal slots.
|
||||
Assert(Type(arrayBuffer) === 'Object'
|
||||
&& 'ArrayBufferData' in arrayBuffer
|
||||
&& 'ArrayBufferByteLength' in arrayBuffer
|
||||
&& 'ArrayBufferDetachKey' in arrayBuffer);
|
||||
// 2. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
|
||||
Assert(IsSharedArrayBuffer(arrayBuffer) === Value.false);
|
||||
// 3. If key is not present, set key to undefined.
|
||||
if (key === undefined) {
|
||||
key = Value.undefined;
|
||||
}
|
||||
// 4. If SameValue(arrayBuffer.[[ArrayBufferDetachKey]], key) is false, throw a TypeError exception.
|
||||
if (SameValue(arrayBuffer.ArrayBufferDetachKey, key) === Value.false) {
|
||||
return surroundingAgent.Throw('TypeError', 'BufferDetachKeyMismatch', key, arrayBuffer);
|
||||
}
|
||||
// 5. Set arrayBuffer.[[ArrayBufferData]] to null.
|
||||
arrayBuffer.ArrayBufferData = Value.null;
|
||||
// 6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
|
||||
arrayBuffer.ArrayBufferByteLength = new Value(0);
|
||||
// 7. Return NormalCompletion(null).
|
||||
return NormalCompletion(Value.null);
|
||||
}
|
||||
|
||||
// #sec-issharedarraybuffer
|
||||
export function IsSharedArrayBuffer(_obj) {
|
||||
return Value.false;
|
||||
}
|
||||
|
||||
export function CloneArrayBuffer(srcBuffer, srcByteOffset, srcLength, cloneConstructor) {
|
||||
// 1. Assert: Type(srcBuffer) is Object and it has an [[ArrayBufferData]] internal slot.
|
||||
Assert(Type(srcBuffer) === 'Object' && 'ArrayBufferData' in srcBuffer);
|
||||
// 2. Assert: IsConstructor(cloneConstructor) is true.
|
||||
Assert(IsConstructor(cloneConstructor) === Value.true);
|
||||
// 3. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength).
|
||||
const targetBuffer = Q(AllocateArrayBuffer(cloneConstructor, srcLength));
|
||||
// 4. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception.
|
||||
if (IsDetachedBuffer(srcBuffer) === Value.true) {
|
||||
return surroundingAgent.Throw('TypeError', 'ArrayBufferDetached');
|
||||
}
|
||||
// 5. Let srcBlock be srcBuffer.[[ArrayBufferData]].
|
||||
const srcBlock = srcBuffer.ArrayBufferData;
|
||||
// 6. Let targetBlock be targetBuffer.[[ArrayBufferData]].
|
||||
const targetBlock = targetBuffer.ArrayBufferData;
|
||||
// 7. Perform CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength).
|
||||
CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset.numberValue(), srcLength.numberValue());
|
||||
// 8. Return targetBuffer.
|
||||
return targetBuffer;
|
||||
}
|
||||
|
||||
// #sec-isbigintelementtype
|
||||
export function IsBigIntElementType(type) {
|
||||
// 1. If type is BigUint64 or BigInt64, return true.
|
||||
if (type === 'BigUint64' || type === 'BigInt64') {
|
||||
return Value.true;
|
||||
}
|
||||
// 2. Return false
|
||||
return Value.false;
|
||||
}
|
||||
|
||||
const throwawayBuffer = new ArrayBuffer(8);
|
||||
const throwawayDataView = new DataView(throwawayBuffer);
|
||||
const throwawayArray = new Uint8Array(throwawayBuffer);
|
||||
|
||||
// #sec-rawbytestonumeric
|
||||
export function RawBytesToNumeric(type, rawBytes, isLittleEndian) {
|
||||
// 1. Let elementSize be the Element Size value specified in Table 61 for Element Type type.
|
||||
const elementSize = typedArrayInfoByType[type].ElementSize;
|
||||
Assert(elementSize === rawBytes.length);
|
||||
const dataViewType = type === 'Uint8C' ? 'Uint8' : type;
|
||||
Object.assign(throwawayArray, rawBytes);
|
||||
return new Value(throwawayDataView[`get${dataViewType}`](0, isLittleEndian === Value.true));
|
||||
}
|
||||
|
||||
// #sec-getvaluefrombuffer
|
||||
export function GetValueFromBuffer(arrayBuffer, byteIndex, type, isTypedArray, order, isLittleEndian) {
|
||||
// 1. Assert: IsDetachedBuffer(arrayBuffer) is false.
|
||||
Assert(IsDetachedBuffer(arrayBuffer) === Value.false);
|
||||
// 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
|
||||
// 3. Assert: ! IsNonNegativeInteger(byteIndex) is true.
|
||||
Assert(X(IsNonNegativeInteger(byteIndex)) === Value.true);
|
||||
// 4. Let block be arrayBuffer.[[ArrayBufferData]].
|
||||
const block = arrayBuffer.ArrayBufferData;
|
||||
// 5. Let elementSize be the Element Size value specified in Table 61 for Element Type type.
|
||||
const elementSize = typedArrayInfoByType[type].ElementSize;
|
||||
// 6. If IsSharedArrayBuffer(arrayBuffer) is true, then
|
||||
if (IsSharedArrayBuffer(arrayBuffer) === Value.true) {
|
||||
Assert(false);
|
||||
}
|
||||
// 7. Else, let rawValue be a List of elementSize containing, in order, the elementSize sequence of bytes starting with block[byteIndex].
|
||||
const rawValue = [...block.subarray(byteIndex.numberValue(), byteIndex.numberValue() + elementSize)];
|
||||
// 8. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
|
||||
if (isLittleEndian === undefined) {
|
||||
isLittleEndian = surroundingAgent.AgentRecord.LittleEndian;
|
||||
}
|
||||
// 9. Return RawBytesToNumeric(type, rawValue, isLittleEndian).
|
||||
return RawBytesToNumeric(type, rawValue, isLittleEndian);
|
||||
}
|
||||
|
||||
const float32NaNLE = Object.freeze([0, 0, 192, 127]);
|
||||
const float32NaNBE = Object.freeze([127, 192, 0, 0]);
|
||||
const float64NaNLE = Object.freeze([0, 0, 0, 0, 0, 0, 248, 127]);
|
||||
const float64NaNBE = Object.freeze([127, 248, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
// #sec-numerictorawbytes
|
||||
export function NumericToRawBytes(type, value, isLittleEndian) {
|
||||
Assert(Type(isLittleEndian) === 'Boolean');
|
||||
isLittleEndian = isLittleEndian === Value.true;
|
||||
let rawBytes;
|
||||
// One day, we will write our own IEEE 754 and two's complement encoder…
|
||||
if (type === 'Float32') {
|
||||
if (Number.isNaN(value.numberValue())) {
|
||||
rawBytes = isLittleEndian ? [...float32NaNLE] : [...float32NaNBE];
|
||||
} else {
|
||||
throwawayDataView.setFloat32(0, value.numberValue(), isLittleEndian);
|
||||
rawBytes = [...throwawayArray.subarray(0, 4)];
|
||||
}
|
||||
} else if (type === 'Float64') {
|
||||
if (Number.isNaN(value.numberValue())) {
|
||||
rawBytes = isLittleEndian ? [...float64NaNLE] : [...float64NaNBE];
|
||||
} else {
|
||||
throwawayDataView.setFloat64(0, value.numberValue(), isLittleEndian);
|
||||
rawBytes = [...throwawayArray.subarray(0, 8)];
|
||||
}
|
||||
} else {
|
||||
// a. Let n be the Element Size value specified in Table 61 for Element Type type.
|
||||
const n = typedArrayInfoByType[type].ElementSize;
|
||||
// b. Let convOp be the abstract operation named in the Conversion Operation column in Table 61 for Element Type type.
|
||||
const convOp = typedArrayInfoByType[type].ConversionOperation;
|
||||
// c. Let intValue be convOp(value) treated as a mathematical value, whether the result is a BigInt or Number.
|
||||
const intValue = X(convOp(value));
|
||||
const dataViewType = type === 'Uint8C' ? 'Uint8' : type;
|
||||
throwawayDataView[`set${dataViewType}`](0, intValue.bigintValue ? intValue.bigintValue() : intValue.numberValue(), isLittleEndian);
|
||||
rawBytes = [...throwawayArray.subarray(0, n)];
|
||||
}
|
||||
return rawBytes;
|
||||
}
|
||||
|
||||
// #sec-setvalueinbuffer
|
||||
export function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order, isLittleEndian) {
|
||||
// 1. Assert: IsDetachedBuffer(arrayBuffer) is false.
|
||||
Assert(IsDetachedBuffer(arrayBuffer) === Value.false);
|
||||
// 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
|
||||
// 3. Assert: ! IsNonNegativeInteger(byteIndex) is true.
|
||||
Assert(X(IsNonNegativeInteger(byteIndex)) === Value.true);
|
||||
// 4. Assert: Type(value) is BigInt if ! IsBigIntElementType(type) is true; otherwise, Type(value) is Number.
|
||||
if (X(IsBigIntElementType(type)) === Value.true) {
|
||||
Assert(Type(value) === 'BigInt');
|
||||
} else {
|
||||
Assert(Type(value) === 'Number');
|
||||
}
|
||||
// 5. Let block be arrayBuffer.[[ArrayBufferData]].
|
||||
const block = arrayBuffer.ArrayBufferData;
|
||||
// 6. Let elementSize be the Element Size value specified in Table 61 for Element Type type.
|
||||
// const elementSize = typedArrayInfo[type].ElementSize;
|
||||
// 7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
|
||||
if (isLittleEndian === undefined) {
|
||||
isLittleEndian = surroundingAgent.AgentRecord.LittleEndian;
|
||||
}
|
||||
// 8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
|
||||
const rawBytes = NumericToRawBytes(type, value, isLittleEndian);
|
||||
// 9. If IsSharedArrayBuffer(arrayBuffer) is true, then
|
||||
if (IsSharedArrayBuffer(arrayBuffer) === Value.true) {
|
||||
Assert(false);
|
||||
}
|
||||
// 10. Else, store the individual bytes of rawBytes into block, in order, starting at block[byteIndex].
|
||||
rawBytes.forEach((byte, i) => {
|
||||
block[byteIndex.numberValue() + i] = byte;
|
||||
});
|
||||
// 11. Return NormalCompletion(undefined).
|
||||
return NormalCompletion(Value.undefined);
|
||||
}
|
||||
Reference in New Issue
Block a user