/ runtime / JSArrayBufferConstructor.cpp
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