1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#ifndef JSArrayBufferViewHelper_h 28#define JSArrayBufferViewHelper_h 29 30#include "ArrayBufferView.h" 31#include "ExceptionCode.h" 32#include "JSArrayBuffer.h" 33#include "JSDOMBinding.h" 34#include <interpreter/CallFrame.h> 35#include <runtime/ArgList.h> 36#include <runtime/Error.h> 37#include <runtime/JSObject.h> 38#include <runtime/JSValue.h> 39 40namespace WebCore { 41 42template <class T> 43JSC::JSValue setWebGLArrayHelper(JSC::ExecState* exec, T* impl, T* (*conversionFunc)(JSC::JSValue)) 44{ 45 if (exec->argumentCount() < 1) 46 return JSC::throwSyntaxError(exec); 47 48 T* array = (*conversionFunc)(exec->argument(0)); 49 if (array) { 50 // void set(in WebGL<T>Array array, [Optional] in unsigned long offset); 51 unsigned offset = 0; 52 if (exec->argumentCount() == 2) 53 offset = exec->argument(1).toInt32(exec); 54 ExceptionCode ec = 0; 55 impl->set(array, offset, ec); 56 setDOMException(exec, ec); 57 return JSC::jsUndefined(); 58 } 59 60 if (exec->argument(0).isObject()) { 61 // void set(in sequence<long> array, [Optional] in unsigned long offset); 62 JSC::JSObject* array = JSC::asObject(exec->argument(0)); 63 uint32_t offset = 0; 64 if (exec->argumentCount() == 2) 65 offset = exec->argument(1).toInt32(exec); 66 uint32_t length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); 67 if (offset > impl->length() 68 || offset + length > impl->length() 69 || offset + length < offset) 70 setDOMException(exec, INDEX_SIZE_ERR); 71 else { 72 for (uint32_t i = 0; i < length; i++) { 73 JSC::JSValue v = array->get(exec, i); 74 if (exec->hadException()) 75 return JSC::jsUndefined(); 76 impl->set(i + offset, v.toNumber(exec)); 77 } 78 } 79 80 return JSC::jsUndefined(); 81 } 82 83 return JSC::throwSyntaxError(exec); 84} 85 86// Template function used by XXXArrayConstructors. 87// If this returns 0, it will already have thrown a JavaScript exception. 88template<class C, typename T> 89PassRefPtr<C> constructArrayBufferViewWithArrayBufferArgument(JSC::ExecState* exec) 90{ 91 RefPtr<ArrayBuffer> buffer = toArrayBuffer(exec->argument(0)); 92 if (!buffer) 93 return 0; 94 95 unsigned offset = (exec->argumentCount() > 1) ? exec->argument(1).toUInt32(exec) : 0; 96 if ((buffer->byteLength() - offset) % sizeof(T)) 97 throwError(exec, createRangeError(exec, "ArrayBuffer length minus the byteOffset is not a multiple of the element size.")); 98 unsigned int length = (buffer->byteLength() - offset) / sizeof(T); 99 if (exec->argumentCount() > 2) 100 length = exec->argument(2).toUInt32(exec); 101 RefPtr<C> array = C::create(buffer, offset, length); 102 if (!array) 103 setDOMException(exec, INDEX_SIZE_ERR); 104 return array; 105} 106 107template<class C, typename T> 108PassRefPtr<C> constructArrayBufferView(JSC::ExecState* exec) 109{ 110 // There are 3 constructors: 111 // 112 // 1) (in int size) 113 // 2) (in ArrayBuffer buffer, [Optional] in int offset, [Optional] in unsigned int length) 114 // 3) (in sequence<T>) - This ends up being a JS "array-like" object 115 // 116 // For the 0 args case, just create a zero-length view. We could 117 // consider raising a SyntaxError for this case, but not all 118 // JavaScript DOM bindings can distinguish between "new 119 // <Type>Array()" and what occurs when a previously-constructed 120 // ArrayBufferView is returned to JavaScript; e.g., from 121 // "array.subset()". 122 if (exec->argumentCount() < 1) 123 return C::create(0); 124 125 if (exec->argument(0).isNull()) { 126 // Invalid first argument 127 throwTypeError(exec); 128 return 0; 129 } 130 131 if (exec->argument(0).isObject()) { 132 RefPtr<C> view = constructArrayBufferViewWithArrayBufferArgument<C, T>(exec); 133 if (view) 134 return view; 135 136 JSC::JSObject* srcArray = asObject(exec->argument(0)); 137 uint32_t length = srcArray->get(exec, JSC::Identifier(exec, "length")).toUInt32(exec); 138 RefPtr<C> array = C::create(length); 139 if (!array) { 140 setDOMException(exec, INDEX_SIZE_ERR); 141 return array; 142 } 143 144 for (unsigned i = 0; i < length; ++i) { 145 JSC::JSValue v = srcArray->get(exec, i); 146 array->set(i, v.toNumber(exec)); 147 } 148 return array; 149 } 150 151 int length = exec->argument(0).toInt32(exec); 152 RefPtr<C> result; 153 if (length >= 0) 154 result = C::create(static_cast<unsigned>(length)); 155 if (!result) 156 throwError(exec, createRangeError(exec, "ArrayBufferView size is not a small enough positive integer.")); 157 return result; 158} 159 160template <typename JSType, typename WebCoreType> 161static JSC::JSValue toJSArrayBufferView(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebCoreType* object) 162{ 163 if (!object) 164 return JSC::jsNull(); 165 166 if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), object)) 167 return wrapper; 168 169 exec->heap()->reportExtraMemoryCost(object->byteLength()); 170 return createWrapper<JSType>(exec, globalObject, object); 171} 172 173} // namespace WebCore 174 175#endif // JSArrayBufferViewHelper_h 176