JSArrayBufferConstructor.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 "JSArrayBufferConstructor.h" 28 29 #include "BuiltinNames.h" 30 #include "JSArrayBuffer.h" 31 #include "JSArrayBufferPrototype.h" 32 #include "JSArrayBufferView.h" 33 #include "JSCInlines.h" 34 35 namespace JSC { 36 37 static JSC_DECLARE_HOST_FUNCTION(arrayBufferFuncIsView); 38 static JSC_DECLARE_HOST_FUNCTION(callArrayBuffer); 39 static JSC_DECLARE_HOST_FUNCTION(constructArrayBuffer); 40 static JSC_DECLARE_HOST_FUNCTION(constructSharedArrayBuffer); 41 42 template<> 43 const ClassInfo JSArrayBufferConstructor::s_info = { 44 "Function", &Base::s_info, nullptr, nullptr, 45 CREATE_METHOD_TABLE(JSArrayBufferConstructor) 46 }; 47 48 template<> 49 const ClassInfo JSSharedArrayBufferConstructor::s_info = { 50 "Function", &Base::s_info, nullptr, nullptr, 51 CREATE_METHOD_TABLE(JSSharedArrayBufferConstructor) 52 }; 53 54 template<ArrayBufferSharingMode sharingMode> 55 JSGenericArrayBufferConstructor<sharingMode>::JSGenericArrayBufferConstructor(VM& vm, Structure* structure) 56 : Base(vm, structure, callArrayBuffer, sharingMode == ArrayBufferSharingMode::Default ? constructArrayBuffer : constructSharedArrayBuffer) 57 { 58 } 59 60 template<ArrayBufferSharingMode sharingMode> 61 void JSGenericArrayBufferConstructor<sharingMode>::finishCreation(VM& vm, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol) 62 { 63 Base::finishCreation(vm, 1, arrayBufferSharingModeName(sharingMode), PropertyAdditionMode::WithoutStructureTransition); 64 putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); 65 putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum); 66 67 if (sharingMode == ArrayBufferSharingMode::Default) { 68 JSGlobalObject* globalObject = this->globalObject(); 69 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isView, arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); 70 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().isViewPrivateName(), arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); 71 } 72 } 73 74 template<ArrayBufferSharingMode sharingMode> 75 EncodedJSValue JSGenericArrayBufferConstructor<sharingMode>::constructImpl(JSGlobalObject* globalObject, CallFrame* callFrame) 76 { 77 VM& vm = globalObject->vm(); 78 auto scope = DECLARE_THROW_SCOPE(vm); 79 80 JSObject* newTarget = asObject(callFrame->newTarget()); 81 Structure* arrayBufferStructure = newTarget == callFrame->jsCallee() 82 ? globalObject->arrayBufferStructure(sharingMode) 83 : InternalFunction::createSubclassStructure(globalObject, newTarget, getFunctionRealm(vm, newTarget)->arrayBufferStructure(sharingMode)); 84 RETURN_IF_EXCEPTION(scope, { }); 85 86 unsigned length; 87 if (callFrame->argumentCount()) { 88 length = callFrame->uncheckedArgument(0).toIndex(globalObject, "length"); 89 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 90 } else { 91 // Although the documentation doesn't say so, it is in fact correct to say 92 // "new ArrayBuffer()". The result is the same as allocating an array buffer 93 // with a zero length. 94 length = 0; 95 } 96 97 auto buffer = ArrayBuffer::tryCreate(length, 1); 98 if (!buffer) 99 return JSValue::encode(throwOutOfMemoryError(globalObject, scope)); 100 101 if (sharingMode == ArrayBufferSharingMode::Shared) 102 buffer->makeShared(); 103 ASSERT(sharingMode == buffer->sharingMode()); 104 105 JSArrayBuffer* result = JSArrayBuffer::create(vm, arrayBufferStructure, WTFMove(buffer)); 106 return JSValue::encode(result); 107 } 108 109 template<ArrayBufferSharingMode sharingMode> 110 Structure* JSGenericArrayBufferConstructor<sharingMode>::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 111 { 112 return Structure::create(vm, globalObject, prototype, TypeInfo(InternalFunctionType, StructureFlags), info()); 113 } 114 115 template<ArrayBufferSharingMode sharingMode> 116 const ClassInfo* JSGenericArrayBufferConstructor<sharingMode>::info() 117 { 118 return &JSGenericArrayBufferConstructor<sharingMode>::s_info; 119 } 120 121 JSC_DEFINE_HOST_FUNCTION(callArrayBuffer, (JSGlobalObject* globalObject, CallFrame*)) 122 { 123 VM& vm = globalObject->vm(); 124 auto scope = DECLARE_THROW_SCOPE(vm); 125 return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(globalObject, scope, "ArrayBuffer")); 126 } 127 128 JSC_DEFINE_HOST_FUNCTION(constructArrayBuffer, (JSGlobalObject* globalObject, CallFrame* callFrame)) 129 { 130 return JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>::constructImpl(globalObject, callFrame); 131 } 132 133 JSC_DEFINE_HOST_FUNCTION(constructSharedArrayBuffer, (JSGlobalObject* globalObject, CallFrame* callFrame)) 134 { 135 return JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared>::constructImpl(globalObject, callFrame); 136 } 137 138 // ------------------------------ Functions -------------------------------- 139 140 // ECMA 24.1.3.1 141 JSC_DEFINE_HOST_FUNCTION(arrayBufferFuncIsView, (JSGlobalObject* globalObject, CallFrame* callFrame)) 142 { 143 return JSValue::encode(jsBoolean(jsDynamicCast<JSArrayBufferView*>(globalObject->vm(), callFrame->argument(0)))); 144 } 145 146 // Instantiate JSGenericArrayBufferConstructors. 147 template class JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared>; 148 template class JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>; 149 150 } // namespace JSC 151