Skip to content

Commit 4f18004

Browse files
authored
Normative: Report assignment failure to canonical numeric properties of immutable TypedArrays (merge #29)
2 parents 94efda2 + 39c2484 commit 4f18004

File tree

1 file changed

+27
-94
lines changed

1 file changed

+27
-94
lines changed

spec.emu

+27-94
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,11 @@ contributors: Mark S. Miller, Richard Gibson
105105
1. If _Desc_ has an [[Enumerable]] field and _Desc_.[[Enumerable]] is *false*, return *false*.
106106
1. If IsAccessorDescriptor(_Desc_) is *true*, return *false*.
107107
1. If _Desc_ has a [[Writable]] field and _Desc_.[[Writable]] is <del>*false*</del> <ins>not _mutable_</ins>, return *false*.
108-
1. <ins>If _Desc_ has a [[Value]] field and _mutable_ is *false* and SameValue(_Desc_.[[Value]], TypedArrayGetElement(_O_, _numericIndex_)) is *false*, return *false*.</ins>
109-
1. If _Desc_ has a [[Value]] field <ins>and _mutable_ is *true*</ins>, perform ? TypedArraySetElement(_O_, _numericIndex_, _Desc_.[[Value]]).
108+
1. <del>If _Desc_ has a [[Value]] field, perform ? TypedArraySetElement(_O_, _numericIndex_, _Desc_.[[Value]]).</del>
109+
1. <ins>If _Desc_ has a [[Value]] field, then</ins>
110+
1. <ins>NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.</ins>
111+
1. <ins>If _mutable_ is *false* and SameValue(_Desc_.[[Value]], TypedArrayGetElement(_O_, _numericIndex_)) is *false*, return *false*.</ins>
112+
1. <ins>If _mutable_ is *true*, perform ? TypedArraySetElement(_O_, _numericIndex_, _Desc_.[[Value]]).</ins>
110113
1. Return *true*.
111114
1. Return ! OrdinaryDefineOwnProperty(_O_, _P_, _Desc_).
112115
</emu-alg>
@@ -128,8 +131,9 @@ contributors: Mark S. Miller, Richard Gibson
128131
1. If _P_ is a String, then
129132
1. Let _numericIndex_ be CanonicalNumericIndexString(_P_).
130133
1. If _numericIndex_ is not *undefined*, then
134+
1. <ins>NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.</ins>
135+
1. <ins>If IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, return *false*.</ins>
131136
1. If SameValue(_O_, _Receiver_) is *true*, then
132-
1. <ins>IsValidIntegerIndex(_O_, _numericIndex_) is *true* and IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, return *false*.</ins>
133137
1. Perform ? TypedArraySetElement(_O_, _numericIndex_, _V_).
134138
1. Return *true*.
135139
1. If IsValidIntegerIndex(_O_, _numericIndex_) is *false*, return *true*.
@@ -148,9 +152,10 @@ contributors: Mark S. Miller, Richard Gibson
148152
<dl class="header">
149153
</dl>
150154
<emu-alg>
155+
1. <ins>Assert: IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *false*.</ins>
151156
1. If _O_.[[ContentType]] is ~bigint~, let _numValue_ be ? ToBigInt(_value_).
152157
1. Otherwise, let _numValue_ be ? ToNumber(_value_).
153-
1. If IsValidIntegerIndex(_O_, _index_) is *true* <ins>and IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *false*</ins>, then
158+
1. If IsValidIntegerIndex(_O_, _index_) is *true*, then
154159
1. Let _offset_ be _O_.[[ByteOffset]].
155160
1. Let _elementSize_ be TypedArrayElementSize(_O_).
156161
1. Let _byteIndexInBuffer_ be (ℝ(_index_) × _elementSize_) + _offset_.
@@ -159,7 +164,7 @@ contributors: Mark S. Miller, Richard Gibson
159164
1. Return ~unused~.
160165
</emu-alg>
161166
<emu-note>
162-
<p>This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached <ins>or immutable</ins> ArrayBuffer.</p>
167+
<p>This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.</p>
163168
</emu-note>
164169
</emu-clause>
165170
</emu-clause>
@@ -284,95 +289,23 @@ contributors: Mark S. Miller, Richard Gibson
284289

285290
<emu-clause id="sec-%typedarray%.prototype.set" oldids="sec-%typedarray%.prototype.set-overloaded-offset" number="26">
286291
<h1>%TypedArray%.prototype.set ( _source_ [ , _offset_ ] )</h1>
287-
288-
<emu-clause id="sec-settypedarrayfromtypedarray" type="abstract operation" oldids="sec-%typedarray%.prototype.set-typedarray-offset">
289-
<h1>
290-
SetTypedArrayFromTypedArray (
291-
_target_: a TypedArray,
292-
_targetOffset_: a non-negative integer or +&infin;,
293-
_source_: a TypedArray,
294-
): either a normal completion containing ~unused~ or a throw completion
295-
</h1>
296-
<dl class="header">
297-
<dt>description</dt>
298-
<dd>It sets multiple values in _target_, starting at index _targetOffset_, reading the values from _source_.</dd>
299-
</dl>
300-
<emu-alg>
301-
1. Let _targetBuffer_ be _target_.[[ViewedArrayBuffer]].
302-
1. Let _targetRecord_ be MakeTypedArrayWithBufferWitnessRecord(_target_, ~seq-cst~).
303-
1. If IsTypedArrayOutOfBounds(_targetRecord_) is *true*, throw a *TypeError* exception.
304-
1. <ins>If IsImmutableBuffer(_target_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception.</ins>
305-
1. Let _targetLength_ be TypedArrayLength(_targetRecord_).
306-
1. Let _srcBuffer_ be _source_.[[ViewedArrayBuffer]].
307-
1. Let _srcRecord_ be MakeTypedArrayWithBufferWitnessRecord(_source_, ~seq-cst~).
308-
1. If IsTypedArrayOutOfBounds(_srcRecord_) is *true*, throw a *TypeError* exception.
309-
1. Let _srcLength_ be TypedArrayLength(_srcRecord_).
310-
1. Let _targetType_ be TypedArrayElementType(_target_).
311-
1. Let _targetElementSize_ be TypedArrayElementSize(_target_).
312-
1. Let _targetByteOffset_ be _target_.[[ByteOffset]].
313-
1. Let _srcType_ be TypedArrayElementType(_source_).
314-
1. Let _srcElementSize_ be TypedArrayElementSize(_source_).
315-
1. Let _srcByteOffset_ be _source_.[[ByteOffset]].
316-
1. If _targetOffset_ = +∞, throw a *RangeError* exception.
317-
1. If _srcLength_ + _targetOffset_ > _targetLength_, throw a *RangeError* exception.
318-
1. If _target_.[[ContentType]] is not _source_.[[ContentType]], throw a *TypeError* exception.
319-
1. If IsSharedArrayBuffer(_srcBuffer_) is *true*, IsSharedArrayBuffer(_targetBuffer_) is *true*, and _srcBuffer_.[[ArrayBufferData]] is _targetBuffer_.[[ArrayBufferData]], let _sameSharedArrayBuffer_ be *true*; otherwise, let _sameSharedArrayBuffer_ be *false*.
320-
1. If SameValue(_srcBuffer_, _targetBuffer_) is *true* or _sameSharedArrayBuffer_ is *true*, then
321-
1. Let _srcByteLength_ be TypedArrayByteLength(_srcRecord_).
322-
1. Set _srcBuffer_ to ? CloneArrayBuffer(_srcBuffer_, _srcByteOffset_, _srcByteLength_).
323-
1. Let _srcByteIndex_ be 0.
324-
1. Else,
325-
1. Let _srcByteIndex_ be _srcByteOffset_.
326-
1. Let _targetByteIndex_ be (_targetOffset_ × _targetElementSize_) + _targetByteOffset_.
327-
1. Let _limit_ be _targetByteIndex_ + (_targetElementSize_ × _srcLength_).
328-
1. If _srcType_ is _targetType_, then
329-
1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
330-
1. Repeat, while _targetByteIndex_ &lt; _limit_,
331-
1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, ~uint8~, *true*, ~unordered~).
332-
1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, ~uint8~, _value_, *true*, ~unordered~).
333-
1. Set _srcByteIndex_ to _srcByteIndex_ + 1.
334-
1. Set _targetByteIndex_ to _targetByteIndex_ + 1.
335-
1. Else,
336-
1. Repeat, while _targetByteIndex_ &lt; _limit_,
337-
1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, _srcType_, *true*, ~unordered~).
338-
1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, _targetType_, _value_, *true*, ~unordered~).
339-
1. Set _srcByteIndex_ to _srcByteIndex_ + _srcElementSize_.
340-
1. Set _targetByteIndex_ to _targetByteIndex_ + _targetElementSize_.
341-
1. Return ~unused~.
342-
</emu-alg>
343-
</emu-clause>
344-
345-
<emu-clause id="sec-settypedarrayfromarraylike" type="abstract operation" oldids="sec-%typedarray%.prototype.set-array-offset">
346-
<h1>
347-
SetTypedArrayFromArrayLike (
348-
_target_: a TypedArray,
349-
_targetOffset_: a non-negative integer or +&infin;,
350-
_source_: an ECMAScript language value, but not a TypedArray,
351-
): either a normal completion containing ~unused~ or a throw completion
352-
</h1>
353-
<dl class="header">
354-
<dt>description</dt>
355-
<dd>It sets multiple values in _target_, starting at index _targetOffset_, reading the values from _source_.</dd>
356-
</dl>
357-
<emu-alg>
358-
1. Let _targetRecord_ be MakeTypedArrayWithBufferWitnessRecord(_target_, ~seq-cst~).
359-
1. If IsTypedArrayOutOfBounds(_targetRecord_) is *true*, throw a *TypeError* exception.
360-
1. <ins>If IsImmutableBuffer(_target_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception.</ins>
361-
1. Let _targetLength_ be TypedArrayLength(_targetRecord_).
362-
1. Let _src_ be ? ToObject(_source_).
363-
1. Let _srcLength_ be ? LengthOfArrayLike(_src_).
364-
1. If _targetOffset_ = +∞, throw a *RangeError* exception.
365-
1. If _srcLength_ + _targetOffset_ > _targetLength_, throw a *RangeError* exception.
366-
1. Let _k_ be 0.
367-
1. Repeat, while _k_ &lt; _srcLength_,
368-
1. Let _Pk_ be ! ToString(𝔽(_k_)).
369-
1. Let _value_ be ? Get(_src_, _Pk_).
370-
1. Let _targetIndex_ be 𝔽(_targetOffset_ + _k_).
371-
1. Perform ? TypedArraySetElement(_target_, _targetIndex_, _value_).
372-
1. Set _k_ to _k_ + 1.
373-
1. Return ~unused~.
374-
</emu-alg>
375-
</emu-clause>
292+
<p>This method sets multiple values in this _TypedArray_, reading the values from _source_. The details differ based upon the type of _source_. The optional _offset_ value indicates the first element index in this _TypedArray_ where values are written. If omitted, it is assumed to be 0.</p>
293+
<p>It performs the following steps when called:</p>
294+
<emu-alg>
295+
1. Let _target_ be the *this* value.
296+
1. <ins>NOTE: The following steps could be simplified by using ? ValidateTypedArray(_target_, ~seq-cst~, ~write~) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns *true* and _offset_ is negative. Regardless, such a change is still worth pursuing if possible.</ins>
297+
1. Perform ? RequireInternalSlot(_target_, [[TypedArrayName]]).
298+
1. Assert: _target_ has a [[ViewedArrayBuffer]] internal slot.
299+
1. <ins>If IsImmutableBuffer(_target_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception.</ins>
300+
1. Let _targetOffset_ be ? ToIntegerOrInfinity(_offset_).
301+
1. If _targetOffset_ &lt; 0, throw a *RangeError* exception.
302+
1. If _source_ is an Object that has a [[TypedArrayName]] internal slot, then
303+
1. Perform ? SetTypedArrayFromTypedArray(_target_, _targetOffset_, _source_).
304+
1. Else,
305+
1. Perform ? SetTypedArrayFromArrayLike(_target_, _targetOffset_, _source_).
306+
1. Return *undefined*.
307+
</emu-alg>
308+
<p>This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.</p>
376309
</emu-clause>
377310

378311
<emu-clause id="sec-%typedarray%.prototype.sort" oldids="sec-typedarraysortcompare" number="29">

0 commit comments

Comments
 (0)