EncodedJSValue JSC_HOST_CALL jsDataViewPrototypeFunctionSetFloat64(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSDataView::s_info)) return throwVMTypeError(exec); JSDataView* castedThis = static_cast<JSDataView*>(asObject(thisValue)); ASSERT_GC_OBJECT_INHERITS(castedThis, &JSDataView::s_info); DataView* imp = static_cast<DataView*>(castedThis->impl()); if (exec->argumentCount() < 2) return throwVMError(exec, createSyntaxError(exec, "Not enough arguments")); ExceptionCode ec = 0; unsigned byteOffset(exec->argument(0).toUInt32(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); double value(exec->argument(1).toNumber(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); int argsCount = exec->argumentCount(); if (argsCount <= 2) { imp->setFloat64(byteOffset, value, ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); } bool littleEndian(exec->argument(2).toBoolean(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); imp->setFloat64(byteOffset, value, littleEndian, ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); }
EncodedJSValue getData(ExecState* exec) { JSDataView* dataView = jsDynamicCast<JSDataView*>(exec->thisValue()); if (!dataView) return throwVMError(exec, createTypeError(exec, "Receiver of DataView method must be a DataView")); if (!exec->argumentCount()) return throwVMError(exec, createTypeError(exec, "Need at least one argument (the byteOffset)")); unsigned byteOffset = exec->uncheckedArgument(0).toUInt32(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); bool littleEndian = false; unsigned elementSize = sizeof(typename Adaptor::Type); if (elementSize > 1 && exec->argumentCount() >= 2) { littleEndian = exec->uncheckedArgument(1).toBoolean(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); } unsigned byteLength = dataView->length(); if (elementSize > byteLength || byteOffset > byteLength - elementSize) return throwVMError(exec, createRangeError(exec, "Out of bounds access")); typename Adaptor::Type value = *reinterpret_cast<typename Adaptor::Type*>(static_cast<uint8_t*>(dataView->vector()) + byteOffset); if (needToFlipBytesIfLittleEndian(littleEndian)) value = flipBytes(value); return JSValue::encode(Adaptor::toJSValue(value)); }
EncodedJSValue JSC_HOST_CALL jsDataViewPrototypeFunctionSetUint8(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSDataView::s_info)) return throwVMTypeError(exec); JSDataView* castedThis = static_cast<JSDataView*>(asObject(thisValue)); ASSERT_GC_OBJECT_INHERITS(castedThis, &JSDataView::s_info); return JSValue::encode(castedThis->setUint8(exec)); }
EncodedJSValue JSC_HOST_CALL dataViewProtoGetterByteOffset(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSDataView* view = jsDynamicCast<JSDataView*>(exec->thisValue()); if (!view) return throwVMTypeError(exec, scope, "DataView.prototype.buffer expects |this| to be a DataView object"); return JSValue::encode(jsNumber(view->byteOffset())); }
bool JSDataView::getOwnPropertySlot( JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { JSDataView* thisObject = jsCast<JSDataView*>(object); if (propertyName == exec->propertyNames().byteLength) { slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->m_length)); return true; } if (propertyName == exec->propertyNames().byteOffset) { slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->byteOffset())); return true; } return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); }
EncodedJSValue setData(ExecState* exec) { JSDataView* dataView = jsDynamicCast<JSDataView*>(exec->thisValue()); if (!dataView) return throwVMError(exec, createTypeError(exec, "Receiver of DataView method must be a DataView")); if (exec->argumentCount() < 2) return throwVMError(exec, createTypeError(exec, "Need at least two argument (the byteOffset and value)")); unsigned byteOffset = exec->uncheckedArgument(0).toUInt32(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); const unsigned dataSize = sizeof(typename Adaptor::Type); union { typename Adaptor::Type value; uint8_t rawBytes[dataSize]; } u; u.value = toNativeFromValue<Adaptor>(exec, exec->uncheckedArgument(1)); if (exec->hadException()) return JSValue::encode(jsUndefined()); bool littleEndian = false; unsigned elementSize = sizeof(typename Adaptor::Type); if (elementSize > 1 && exec->argumentCount() >= 3) { littleEndian = exec->uncheckedArgument(2).toBoolean(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); } unsigned byteLength = dataView->length(); if (elementSize > byteLength || byteOffset > byteLength - elementSize) return throwVMError(exec, createRangeError(exec, "Out of bounds access")); uint8_t* dataPtr = static_cast<uint8_t*>(dataView->vector()) + byteOffset; if (needToFlipBytesIfLittleEndian(littleEndian)) { for (unsigned i = dataSize; i--;) *dataPtr++ = u.rawBytes[i]; } else { for (unsigned i = 0; i < dataSize; i++) *dataPtr++ = u.rawBytes[i]; } return JSValue::encode(jsUndefined()); }
EncodedJSValue setData(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSDataView* dataView = jsDynamicCast<JSDataView*>(exec->thisValue()); if (!dataView) return throwVMTypeError(exec, scope, ASCIILiteral("Receiver of DataView method must be a DataView")); unsigned byteOffset = exec->argument(0).toIndex(exec, "byteOffset"); RETURN_IF_EXCEPTION(scope, encodedJSValue()); const unsigned dataSize = sizeof(typename Adaptor::Type); union { typename Adaptor::Type value; uint8_t rawBytes[dataSize]; } u; u.value = toNativeFromValue<Adaptor>(exec, exec->argument(1)); RETURN_IF_EXCEPTION(scope, encodedJSValue()); bool littleEndian = false; unsigned elementSize = sizeof(typename Adaptor::Type); if (elementSize > 1 && exec->argumentCount() >= 3) { littleEndian = exec->uncheckedArgument(2).toBoolean(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); } unsigned byteLength = dataView->length(); if (elementSize > byteLength || byteOffset > byteLength - elementSize) return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("Out of bounds access"))); uint8_t* dataPtr = static_cast<uint8_t*>(dataView->vector()) + byteOffset; if (needToFlipBytesIfLittleEndian(littleEndian)) { for (unsigned i = dataSize; i--;) *dataPtr++ = u.rawBytes[i]; } else { for (unsigned i = 0; i < dataSize; i++) *dataPtr++ = u.rawBytes[i]; } return JSValue::encode(jsUndefined()); }
JSDataView* JSDataView::create( ExecState* exec, Structure* structure, PassRefPtr<ArrayBuffer> passedBuffer, unsigned byteOffset, unsigned byteLength) { RefPtr<ArrayBuffer> buffer = passedBuffer; if (!ArrayBufferView::verifySubRange<uint8_t>(buffer, byteOffset, byteLength)) { throwVMError( exec, createRangeError(exec, "Byte offset and length out of range of buffer")); return 0; } VM& vm = exec->vm(); ConstructionContext context( structure, buffer, byteOffset, byteLength, ConstructionContext::DataView); ASSERT(context); JSDataView* result = new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context, buffer.get()); result->finishCreation(vm); return result; }
JSDataView* JSDataView::create( ExecState* exec, Structure* structure, PassRefPtr<ArrayBuffer> passedBuffer, unsigned byteOffset, unsigned byteLength) { RefPtr<ArrayBuffer> buffer = passedBuffer; if (!ArrayBufferView::verifySubRangeLength(buffer, byteOffset, byteLength, sizeof(uint8_t))) { throwVMError(exec, createRangeError(exec, ASCIILiteral("Length out of range of buffer"))); return nullptr; } if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, sizeof(uint8_t))) { exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Byte offset is not aligned"))); return nullptr; } VM& vm = exec->vm(); ConstructionContext context( structure, buffer, byteOffset, byteLength, ConstructionContext::DataView); ASSERT(context); JSDataView* result = new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context, buffer.get()); result->finishCreation(vm); return result; }
PassRefPtr<ArrayBufferView> JSDataView::getTypedArrayImpl(JSArrayBufferView* object) { JSDataView* thisObject = jsCast<JSDataView*>(object); return thisObject->typedImpl(); }
JSValue jsDataViewConstructor(ExecState* exec, JSValue slotBase, const Identifier&) { JSDataView* domObject = static_cast<JSDataView*>(asObject(slotBase)); return JSDataView::getConstructor(exec, domObject->globalObject()); }