/* * Copyright (C) 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSDataView.h" #include "ArrayBufferView.h" #include "DataView.h" #include "Error.h" #include "JSCInlines.h" #include "Reject.h" namespace JSC { const ClassInfo JSDataView::s_info = { "DataView", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDataView)}; JSDataView::JSDataView(VM& vm, ConstructionContext& context, ArrayBuffer* buffer) : Base(vm, context) , m_buffer(buffer) { } JSDataView* JSDataView::create( ExecState* exec, Structure* structure, PassRefPtr passedBuffer, unsigned byteOffset, unsigned byteLength) { RefPtr 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(vm.heap)) JSDataView(vm, context, buffer.get()); result->finishCreation(vm); return result; } JSDataView* JSDataView::createUninitialized(ExecState*, Structure*, unsigned) { UNREACHABLE_FOR_PLATFORM(); return 0; } JSDataView* JSDataView::create(ExecState*, Structure*, unsigned) { UNREACHABLE_FOR_PLATFORM(); return 0; } bool JSDataView::set(ExecState*, unsigned, JSObject*, unsigned, unsigned) { UNREACHABLE_FOR_PLATFORM(); return false; } bool JSDataView::setIndex(ExecState*, unsigned, JSValue) { UNREACHABLE_FOR_PLATFORM(); return false; } PassRefPtr JSDataView::typedImpl() { return DataView::create(buffer(), byteOffset(), length()); } bool JSDataView::getOwnPropertySlot( JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { JSDataView* thisObject = jsCast(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); } bool JSDataView::put( JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { JSDataView* thisObject = jsCast(cell); if (UNLIKELY(isThisValueAltered(slot, thisObject))) return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode()); if (propertyName == exec->propertyNames().byteLength || propertyName == exec->propertyNames().byteOffset) return reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property."); return Base::put(thisObject, exec, propertyName, value, slot); } bool JSDataView::defineOwnProperty( JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) { JSDataView* thisObject = jsCast(object); if (propertyName == exec->propertyNames().byteLength || propertyName == exec->propertyNames().byteOffset) return reject(exec, shouldThrow, "Attempting to define read-only typed array property."); return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); } bool JSDataView::deleteProperty( JSCell* cell, ExecState* exec, PropertyName propertyName) { JSDataView* thisObject = jsCast(cell); if (propertyName == exec->propertyNames().byteLength || propertyName == exec->propertyNames().byteOffset) return false; return Base::deleteProperty(thisObject, exec, propertyName); } void JSDataView::getOwnNonIndexPropertyNames( JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) { JSDataView* thisObject = jsCast(object); if (mode.includeDontEnumProperties()) { array.add(exec->propertyNames().byteOffset); array.add(exec->propertyNames().byteLength); } Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode); } ArrayBuffer* JSDataView::slowDownAndWasteMemory(JSArrayBufferView*) { UNREACHABLE_FOR_PLATFORM(); return 0; } PassRefPtr JSDataView::getTypedArrayImpl(JSArrayBufferView* object) { JSDataView* thisObject = jsCast(object); return thisObject->typedImpl(); } Structure* JSDataView::createStructure( VM& vm, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create( vm, globalObject, prototype, TypeInfo(DataViewType, StructureFlags), info(), NonArray); } } // namespace JSC