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 "JSArrayBufferPrototype.h"
28
29#include "Error.h"
30#include "ExceptionHelpers.h"
31#include "JSArrayBuffer.h"
32#include "JSFunction.h"
33#include "JSCInlines.h"
34#include "TypedArrayAdaptors.h"
35
36namespace JSC {
37
38static EncodedJSValue JSC_HOST_CALL arrayBufferProtoFuncSlice(ExecState* exec)
39{
40 VM& vm = exec->vm();
41 auto scope = DECLARE_THROW_SCOPE(vm);
42
43 JSFunction* callee = jsCast<JSFunction*>(exec->jsCallee());
44
45 JSArrayBuffer* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, exec->thisValue());
46 if (!thisObject || thisObject->impl()->isShared())
47 return throwVMTypeError(exec, scope, "Receiver of slice must be an ArrayBuffer."_s);
48
49 double begin = exec->argument(0).toInteger(exec);
50 RETURN_IF_EXCEPTION(scope, encodedJSValue());
51
52 double end;
53 if (!exec->argument(1).isUndefined()) {
54 end = exec->uncheckedArgument(1).toInteger(exec);
55 RETURN_IF_EXCEPTION(scope, encodedJSValue());
56 } else
57 end = thisObject->impl()->byteLength();
58
59 auto newBuffer = thisObject->impl()->slice(begin, end);
60
61 Structure* structure = callee->globalObject(vm)->arrayBufferStructure(newBuffer->sharingMode());
62
63 JSArrayBuffer* result = JSArrayBuffer::create(vm, structure, WTFMove(newBuffer));
64
65 return JSValue::encode(result);
66}
67
68// http://tc39.github.io/ecmascript_sharedmem/shmem.html#sec-get-arraybuffer.prototype.bytelength
69static EncodedJSValue JSC_HOST_CALL arrayBufferProtoGetterFuncByteLength(ExecState* exec)
70{
71 VM& vm = exec->vm();
72 auto scope = DECLARE_THROW_SCOPE(vm);
73 JSValue thisValue = exec->thisValue();
74 if (!thisValue.isObject())
75 return throwVMTypeError(exec, scope, "Receiver should be an array buffer but was not an object"_s);
76
77 auto* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, thisValue);
78 if (!thisObject)
79 return throwVMTypeError(exec, scope, "Receiver should be an array buffer"_s);
80 if (thisObject->isShared())
81 return throwVMTypeError(exec, scope, "Receiver should not be a shared array buffer"_s);
82
83 RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(thisObject->impl()->byteLength())));
84}
85
86// http://tc39.github.io/ecmascript_sharedmem/shmem.html#StructuredData.SharedArrayBuffer.prototype.get_byteLength
87static EncodedJSValue JSC_HOST_CALL sharedArrayBufferProtoGetterFuncByteLength(ExecState* exec)
88{
89 VM& vm = exec->vm();
90 auto scope = DECLARE_THROW_SCOPE(vm);
91 JSValue thisValue = exec->thisValue();
92 if (!thisValue.isObject())
93 return throwVMTypeError(exec, scope, "Receiver should be an array buffer but was not an object"_s);
94
95 auto* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, thisValue);
96 if (!thisObject)
97 return throwVMTypeError(exec, scope, "Receiver should be an array buffer"_s);
98 if (!thisObject->isShared())
99 return throwVMTypeError(exec, scope, "Receiver should be a shared array buffer"_s);
100
101 RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(thisObject->impl()->byteLength())));
102}
103
104const ClassInfo JSArrayBufferPrototype::s_info = {
105 "ArrayBufferPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferPrototype)
106};
107
108JSArrayBufferPrototype::JSArrayBufferPrototype(VM& vm, Structure* structure, ArrayBufferSharingMode sharingMode)
109 : Base(vm, structure)
110 , m_sharingMode(sharingMode)
111{
112}
113
114void JSArrayBufferPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
115{
116 Base::finishCreation(vm);
117
118 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayBufferProtoFuncSlice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
119 putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, arrayBufferSharingModeName(m_sharingMode)), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
120 if (m_sharingMode == ArrayBufferSharingMode::Default)
121 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->byteLength, arrayBufferProtoGetterFuncByteLength, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
122 else
123 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->byteLength, sharedArrayBufferProtoGetterFuncByteLength, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
124}
125
126JSArrayBufferPrototype* JSArrayBufferPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, ArrayBufferSharingMode sharingMode)
127{
128 JSArrayBufferPrototype* prototype =
129 new (NotNull, allocateCell<JSArrayBufferPrototype>(vm.heap))
130 JSArrayBufferPrototype(vm, structure, sharingMode);
131 prototype->finishCreation(vm, globalObject);
132 return prototype;
133}
134
135Structure* JSArrayBufferPrototype::createStructure(
136 VM& vm, JSGlobalObject* globalObject, JSValue prototype)
137{
138 return Structure::create(
139 vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
140}
141
142} // namespace JSC
143
144