| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- // Implements typed array.
- //----------------------------------------------------------------------------
- #include "RuntimeLibraryPch.h"
- namespace Js
- {
- Var DataView::NewInstance(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- Var newTarget = args.GetNewTarget();
- bool isCtorSuperCall = JavascriptOperators::GetAndAssertIsConstructorSuperCall(args);
- uint32 byteLength = 0;
- uint32 mappedLength;
- int32 offset = 0;
- ArrayBufferBase* arrayBuffer = nullptr;
- DataView* dataView;
- //1. If NewTarget is undefined, throw a TypeError exception.
- if (!(callInfo.Flags & CallFlags_New) || (newTarget && JavascriptOperators::IsUndefinedObject(newTarget)))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_ClassConstructorCannotBeCalledWithoutNew, _u("DataView"));
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("buffer"));
- }
- // Currently the only reason we check for an external object is projection related, so it remains under conditional compilation.
- RecyclableObject* jsArraySource = NULL;
- if (JavascriptOperators::IsObject(args[1]) && JavascriptConversion::ToObject(args[1], scriptContext, &jsArraySource))
- {
- ArrayBuffer *ab = nullptr;
- HRESULT hr = scriptContext->GetHostScriptContext()->ArrayBufferFromExternalObject(jsArraySource, &ab);
- switch (hr)
- {
- case S_OK:
- case S_FALSE:
- arrayBuffer = ab;
- // Both of these cases will be handled by the arrayBuffer null check.
- break;
- default:
- // Any FAILURE HRESULT or unexpected HRESULT.
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_InvalidArgument, _u("buffer"));
- break;
- }
- }
- //2. If Type(buffer) is not Object, throw a TypeError exception.
- //3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
- if (arrayBuffer == nullptr)
- {
- if (VarIs<ArrayBufferBase>(args[1]))
- {
- arrayBuffer = VarTo<ArrayBufferBase>(args[1]);
- }
- else
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject, _u("buffer"));
- }
- }
- //4. Let offset be ToIndex(byteOffset).
- if (args.Info.Count > 2)
- {
- Var secondArgument = args[2];
- offset = ArrayBuffer::ToIndex(secondArgument, JSERR_ArrayLengthConstructIncorrect, scriptContext, ArrayBuffer::MaxArrayBufferLength, false);
- }
- //5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
- if (arrayBuffer->IsDetached())
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
- }
- //6. Let bufferByteLength be the value of buffer's[[ArrayBufferByteLength]] internal slot.
- //7. If offset > bufferByteLength, throw a RangeError exception.
- byteLength = arrayBuffer->GetByteLength();
- if ((uint32)offset > byteLength)
- {
- JavascriptError::ThrowRangeError(
- scriptContext, JSERR_DataView_InvalidArgument, _u("byteOffset"));
- }
- //8. If byteLength is either not present or is undefined, then
- // a. Let viewByteLength be bufferByteLength - offset.
- //9. Else,
- // a. Let viewByteLength be ToIndex(byteLength).
- // b. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
- if (args.Info.Count > 3 && !JavascriptOperators::IsUndefinedObject(args[3]))
- {
- Var thirdArgument = args[3];
- mappedLength = ArrayBuffer::ToIndex(thirdArgument, JSERR_ArrayLengthConstructIncorrect, scriptContext, ArrayBuffer::MaxArrayBufferLength, false);
- uint32 viewRange = mappedLength + offset;
- if (viewRange > byteLength || viewRange < mappedLength) // overflow indicates out-of-range
- {
- JavascriptError::ThrowRangeError(
- scriptContext, JSERR_DataView_InvalidArgument, _u("byteLength"));
- }
- }
- else
- {
- mappedLength = byteLength - offset;
- }
- // Evaluation of the argument(s) above is reentrant and can detach the array.
- if (arrayBuffer->IsDetached())
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
- }
- //10. Let O be OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]).
- //11. Set O's[[DataView]] internal slot to true.
- //12. Set O's[[ViewedArrayBuffer]] internal slot to buffer.
- //13. Set O's[[ByteLength]] internal slot to viewByteLength.
- //14. Set O's[[ByteOffset]] internal slot to offset.
- //15. Return O.
- dataView = scriptContext->GetLibrary()->CreateDataView(arrayBuffer, offset, mappedLength);
- return isCtorSuperCall ?
- JavascriptOperators::OrdinaryCreateFromConstructor(VarTo<RecyclableObject>(newTarget), dataView, nullptr, scriptContext) :
- dataView;
- }
- DataView::DataView(ArrayBufferBase* arrayBuffer, uint32 byteoffset, uint32 mappedLength, DynamicType* type)
- : ArrayBufferParent(type, mappedLength, arrayBuffer),
- byteOffset(byteoffset)
- {
- buffer = arrayBuffer->GetBuffer() + byteoffset;
- }
- Var DataView::EntryGetInt8(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->template GetValue<int8>(args[1], _u("DataView.prototype.GetInt8"), FALSE);
- }
- Var DataView::EntryGetUint8(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValue<uint8>(args[1], _u("DataView.prototype.GetUint8"), FALSE);
- }
- Var DataView::EntryGetInt16(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValue<int16>(args[1], _u("DataView.prototype.GetInt16"), isLittleEndian);
- }
- Var DataView::EntryGetUint16(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->template GetValue<uint16>(args[1], _u("DataView.prototype.GetUint16"), isLittleEndian);
- }
- Var DataView::EntryGetUint32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValue<uint32>(args[1], _u("DataView.prototype.GetUint32"), isLittleEndian);
- }
- Var DataView::EntryGetInt32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValue<int32>(args[1], _u("DataView.prototype.GetInt32"), isLittleEndian);
- }
- Var DataView::EntryGetFloat32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValueWithCheck<float>(args[1], _u("DataView.prototype.GetFloat32"), isLittleEndian);
- }
- Var DataView::EntryGetFloat64(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 2)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset"));
- }
- if (args.Info.Count > 2)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[2], scriptContext);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- return dataView->GetValueWithCheck<double>(args[1], _u("DataView.prototype.GetFloat64"), isLittleEndian);
- }
- Var DataView::EntrySetInt8(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- int8 value = JavascriptConversion::ToInt8(args[2], scriptContext);
- dataView->SetValue<int8>(args[1], value, _u("DataView.prototype.SetInt8"));
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetUint8(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- uint8 value = JavascriptConversion::ToUInt8(args[2], scriptContext);
- dataView->SetValue<uint8>(args[1], value, _u("DataView.prototype.SetUint8"));
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetInt16(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- int16 value = JavascriptConversion::ToInt16(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<int16>(args[1], value, _u("DataView.prototype.SetInt16"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetUint16(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- uint16 value = JavascriptConversion::ToUInt16(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<uint16>(args[1], value, _u("DataView.prototype.SetUint16"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetInt32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- int32 value = JavascriptConversion::ToInt32(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<int32>(args[1], value, _u("DataView.prototype.SetInt32"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetUint32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- uint32 value = JavascriptConversion::ToUInt32(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<uint32>(args[1], value, _u("DataView.prototype.SetUint32"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetFloat32(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView, _u("offset or value"));
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- float value = JavascriptConversion::ToFloat(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<float>(args[1], value, _u("DataView.prototype.SetFloat32"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntrySetFloat64(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- BOOL isLittleEndian = FALSE;
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- if (args.Info.Count < 3)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DataView_NeedArgument, _u("offset or value"));
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- double value = JavascriptConversion::ToNumber(args[2], scriptContext);
- if (args.Info.Count > 3)
- {
- isLittleEndian = JavascriptConversion::ToBoolean(args[3], scriptContext);
- }
- dataView->SetValue<double>(args[1], value, _u("DataView.prototype.SetFloat64"), isLittleEndian);
- return scriptContext->GetLibrary()->GetUndefined();
- }
- Var DataView::EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- ArrayBufferBase* arrayBuffer = dataView->GetArrayBuffer();
- if (arrayBuffer == nullptr)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject);
- }
- return CrossSite::MarshalVar(scriptContext, arrayBuffer);
- }
- Var DataView::EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- ArrayBufferBase* arrayBuffer = dataView->GetArrayBuffer();
- if (arrayBuffer == nullptr)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject);
- }
- else if (arrayBuffer->IsDetached())
- {
- return TaggedInt::ToVarUnchecked(0);
- }
- return JavascriptNumber::ToVar(dataView->GetLength(), scriptContext);
- }
- Var DataView::EntryGetterByteOffset(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !VarIs<DataView>(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
- }
- DataView* dataView = VarTo<DataView>(args[0]);
- ArrayBufferBase* arrayBuffer = dataView->GetArrayBuffer();
- if (arrayBuffer == nullptr)
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject);
- }
- else if (arrayBuffer->IsDetached())
- {
- return TaggedInt::ToVarUnchecked(0);
- }
- return JavascriptNumber::ToVar(dataView->GetByteOffset(), scriptContext);
- }
- BOOL DataView::SetItemWithAttributes(uint32 index, Var value, PropertyAttributes attributes)
- {
- AssertMsg(false, "We don't need a DataView to serve as object's internal array");
- return FALSE;
- }
- void DataView::ClearLengthAndBufferOnDetach()
- {
- AssertMsg(this->GetArrayBuffer()->IsDetached(), "Array buffer should be detached if we're calling this method");
- this->length = 0;
- #if INT32VAR
- this->buffer = (BYTE*)TaggedInt::ToVarUnchecked(0);
- #else
- this->buffer = nullptr;
- #endif
- }
- #ifdef _M_ARM
- // Provide template specialization (only) for memory access at unaligned float/double address which causes data alignment exception otherwise.
- template<>
- Var DataView::GetValueWithCheck<float>(Var offset, const char16 *funcName, BOOL isLittleEndian)
- {
- return this->GetValueWithCheck<float, float UNALIGNED*>(offset, isLittleEndian, funcName);
- }
- template<>
- Var DataView::GetValueWithCheck<double>(Var offset, const char16 *funcName, BOOL isLittleEndian)
- {
- return this->GetValueWithCheck<double, double UNALIGNED*>(offset, isLittleEndian, funcName);
- }
- template<>
- void DataView::SetValue<float>(Var offset, float value, const char16 *funcName, BOOL isLittleEndian)
- {
- this->SetValue<float, float UNALIGNED*>(offset, value, isLittleEndian, funcName);
- }
- template<>
- void DataView::SetValue<double>(Var offset, double value, const char16 *funcName, BOOL isLittleEndian)
- {
- this->SetValue<double, double UNALIGNED*>(offset, value, isLittleEndian, funcName);
- }
- #endif
- }
|