All prototypes should call didBecomePrototype()
[WebKit.git] / Source / JavaScriptCore / runtime / JSArrayBufferPrototype.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 "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
36 namespace JSC {
37
38 static 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
69 static 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
87 static 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
104 const ClassInfo JSArrayBufferPrototype::s_info = {
105     "ArrayBufferPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferPrototype)
106 };
107
108 JSArrayBufferPrototype::JSArrayBufferPrototype(VM& vm, Structure* structure, ArrayBufferSharingMode sharingMode)
109     : Base(vm, structure)
110     , m_sharingMode(sharingMode)
111 {
112 }
113
114 void 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     didBecomePrototype();
125 }
126
127 JSArrayBufferPrototype* JSArrayBufferPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, ArrayBufferSharingMode sharingMode)
128 {
129     JSArrayBufferPrototype* prototype =
130         new (NotNull, allocateCell<JSArrayBufferPrototype>(vm.heap))
131         JSArrayBufferPrototype(vm, structure, sharingMode);
132     prototype->finishCreation(vm, globalObject);
133     return prototype;
134 }
135
136 Structure* JSArrayBufferPrototype::createStructure(
137     VM& vm, JSGlobalObject* globalObject, JSValue prototype)
138 {
139     return Structure::create(
140         vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
141 }
142
143 } // namespace JSC
144