Rename the reject() helper function to something more meaningful.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSDataView.cpp
1 /*
2  * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "JSDataView.h"
28
29 #include "ArrayBufferView.h"
30 #include "DataView.h"
31 #include "Error.h"
32 #include "JSCInlines.h"
33 #include "TypeError.h"
34
35 namespace JSC {
36
37 const ClassInfo JSDataView::s_info = {
38     "DataView", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDataView)};
39
40 JSDataView::JSDataView(VM& vm, ConstructionContext& context, ArrayBuffer* buffer)
41     : Base(vm, context)
42     , m_buffer(buffer)
43 {
44 }
45
46 JSDataView* JSDataView::create(
47     ExecState* exec, Structure* structure, PassRefPtr<ArrayBuffer> passedBuffer,
48     unsigned byteOffset, unsigned byteLength)
49 {
50     VM& vm = exec->vm();
51     auto scope = DECLARE_THROW_SCOPE(vm);
52
53     RefPtr<ArrayBuffer> buffer = passedBuffer;
54     if (!ArrayBufferView::verifySubRangeLength(buffer, byteOffset, byteLength, sizeof(uint8_t))) {
55         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("Length out of range of buffer")));
56         return nullptr;
57     }
58     if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, sizeof(uint8_t))) {
59         throwException(exec, scope, createRangeError(exec, ASCIILiteral("Byte offset is not aligned")));
60         return nullptr;
61     }
62     ConstructionContext context(
63         structure, buffer, byteOffset, byteLength, ConstructionContext::DataView);
64     ASSERT(context);
65     JSDataView* result =
66         new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context, buffer.get());
67     result->finishCreation(vm);
68     return result;
69 }
70
71 JSDataView* JSDataView::createUninitialized(ExecState*, Structure*, unsigned)
72 {
73     UNREACHABLE_FOR_PLATFORM();
74     return 0;
75 }
76
77 JSDataView* JSDataView::create(ExecState*, Structure*, unsigned)
78 {
79     UNREACHABLE_FOR_PLATFORM();
80     return 0;
81 }
82
83 bool JSDataView::set(ExecState*, unsigned, JSObject*, unsigned, unsigned)
84 {
85     UNREACHABLE_FOR_PLATFORM();
86     return false;
87 }
88
89 bool JSDataView::setIndex(ExecState*, unsigned, JSValue)
90 {
91     UNREACHABLE_FOR_PLATFORM();
92     return false;
93 }
94
95 PassRefPtr<DataView> JSDataView::typedImpl()
96 {
97     return DataView::create(buffer(), byteOffset(), length());
98 }
99
100 bool JSDataView::getOwnPropertySlot(
101     JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
102 {
103     JSDataView* thisObject = jsCast<JSDataView*>(object);
104     if (propertyName == exec->propertyNames().byteLength) {
105         slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->m_length));
106         return true;
107     }
108     if (propertyName == exec->propertyNames().byteOffset) {
109         slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->byteOffset()));
110         return true;
111     }
112
113     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
114 }
115
116 bool JSDataView::put(
117     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
118     PutPropertySlot& slot)
119 {
120     VM& vm = exec->vm();
121     auto scope = DECLARE_THROW_SCOPE(vm);
122     JSDataView* thisObject = jsCast<JSDataView*>(cell);
123
124     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
125         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
126
127     if (propertyName == vm.propertyNames->byteLength
128         || propertyName == vm.propertyNames->byteOffset)
129         return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral("Attempting to write to read-only typed array property."));
130
131     return Base::put(thisObject, exec, propertyName, value, slot);
132 }
133
134 bool JSDataView::defineOwnProperty(
135     JSObject* object, ExecState* exec, PropertyName propertyName,
136     const PropertyDescriptor& descriptor, bool shouldThrow)
137 {
138     VM& vm = exec->vm();
139     auto scope = DECLARE_THROW_SCOPE(vm);
140     JSDataView* thisObject = jsCast<JSDataView*>(object);
141     if (propertyName == vm.propertyNames->byteLength
142         || propertyName == vm.propertyNames->byteOffset)
143         return typeError(exec, scope, shouldThrow, ASCIILiteral("Attempting to define read-only typed array property."));
144
145     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
146 }
147
148 bool JSDataView::deleteProperty(
149     JSCell* cell, ExecState* exec, PropertyName propertyName)
150 {
151     JSDataView* thisObject = jsCast<JSDataView*>(cell);
152     if (propertyName == exec->propertyNames().byteLength
153         || propertyName == exec->propertyNames().byteOffset)
154         return false;
155
156     return Base::deleteProperty(thisObject, exec, propertyName);
157 }
158
159 void JSDataView::getOwnNonIndexPropertyNames(
160     JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
161 {
162     JSDataView* thisObject = jsCast<JSDataView*>(object);
163     
164     if (mode.includeDontEnumProperties()) {
165         array.add(exec->propertyNames().byteOffset);
166         array.add(exec->propertyNames().byteLength);
167     }
168     
169     Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
170 }
171
172 ArrayBuffer* JSDataView::slowDownAndWasteMemory(JSArrayBufferView*)
173 {
174     UNREACHABLE_FOR_PLATFORM();
175     return 0;
176 }
177
178 PassRefPtr<ArrayBufferView> JSDataView::getTypedArrayImpl(JSArrayBufferView* object)
179 {
180     JSDataView* thisObject = jsCast<JSDataView*>(object);
181     return thisObject->typedImpl();
182 }
183
184 Structure* JSDataView::createStructure(
185     VM& vm, JSGlobalObject* globalObject, JSValue prototype)
186 {
187     return Structure::create(
188         vm, globalObject, prototype, TypeInfo(DataViewType, StructureFlags), info(),
189         NonArray);
190 }
191
192 } // namespace JSC
193