Home | History | Annotate | Download | only in js
      1 /*
      2  * Copyright (C) 2010 Google 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  *
      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 AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "JSDataView.h"
     28 
     29 #include "DataView.h"
     30 #include "ExceptionCode.h"
     31 #include "JSArrayBufferViewHelper.h"
     32 #include <wtf/MathExtras.h>
     33 
     34 using namespace JSC;
     35 
     36 namespace WebCore {
     37 
     38 enum DataViewAccessType {
     39     AccessDataViewMemberAsInt8,
     40     AccessDataViewMemberAsUint8,
     41     AccessDataViewMemberAsFloat32,
     42     AccessDataViewMemberAsFloat64
     43 };
     44 
     45 JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, DataView* object)
     46 {
     47     return wrap<JSDataView>(exec, globalObject, object);
     48 }
     49 
     50 EncodedJSValue JSC_HOST_CALL JSDataViewConstructor::constructJSDataView(ExecState* exec)
     51 {
     52     if (exec->argument(0).isNull() || !exec->argument(0).isObject())
     53         return throwVMTypeError(exec);
     54 
     55     RefPtr<DataView> view = constructArrayBufferViewWithArrayBufferArgument<DataView, char>(exec);
     56     if (!view.get()) {
     57         setDOMException(exec, INDEX_SIZE_ERR);
     58         return JSValue::encode(jsUndefined());
     59     }
     60 
     61     JSDataViewConstructor* jsConstructor = static_cast<JSDataViewConstructor*>(exec->callee());
     62     return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), view.get())));
     63 }
     64 
     65 static JSValue getDataViewMember(ExecState* exec, DataView* imp, DataViewAccessType type)
     66 {
     67     if (exec->argumentCount() < 1)
     68         return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
     69     ExceptionCode ec = 0;
     70     unsigned byteOffset = exec->argument(0).toUInt32(exec);
     71     if (exec->hadException())
     72         return jsUndefined();
     73 
     74     bool littleEndian = false;
     75     if (exec->argumentCount() > 1 && (type == AccessDataViewMemberAsFloat32 || type == AccessDataViewMemberAsFloat64)) {
     76         littleEndian = exec->argument(1).toBoolean(exec);
     77         if (exec->hadException())
     78             return jsUndefined();
     79     }
     80 
     81     JSC::JSValue result;
     82     switch (type) {
     83     case AccessDataViewMemberAsInt8:
     84         result = jsNumber(imp->getInt8(byteOffset, ec));
     85         break;
     86     case AccessDataViewMemberAsUint8:
     87         result = jsNumber(imp->getUint8(byteOffset, ec));
     88         break;
     89     case AccessDataViewMemberAsFloat32:
     90     case AccessDataViewMemberAsFloat64: {
     91         double value = (type == AccessDataViewMemberAsFloat32) ? imp->getFloat32(byteOffset, littleEndian, ec) : imp->getFloat64(byteOffset, littleEndian, ec);
     92         result = isnan(value) ? JSValue(nonInlineNaN()) : jsNumber(value);
     93         break;
     94     } default:
     95         ASSERT_NOT_REACHED();
     96         break;
     97     }
     98     setDOMException(exec, ec);
     99     return result;
    100 }
    101 
    102 JSValue JSDataView::getInt8(ExecState* exec)
    103 {
    104     return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsInt8);
    105 }
    106 
    107 JSValue JSDataView::getUint8(ExecState* exec)
    108 {
    109     return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsUint8);
    110 }
    111 
    112 JSValue JSDataView::getFloat32(ExecState* exec)
    113 {
    114     return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsFloat32);
    115 }
    116 
    117 JSValue JSDataView::getFloat64(ExecState* exec)
    118 {
    119     return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsFloat64);
    120 }
    121 
    122 static JSValue setDataViewMember(ExecState* exec, DataView* imp, DataViewAccessType type)
    123 {
    124     if (exec->argumentCount() < 2)
    125         return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
    126     ExceptionCode ec = 0;
    127     unsigned byteOffset = exec->argument(0).toUInt32(exec);
    128     if (exec->hadException())
    129         return jsUndefined();
    130     int value = exec->argument(1).toInt32(exec);
    131     if (exec->hadException())
    132         return jsUndefined();
    133 
    134     switch (type) {
    135     case AccessDataViewMemberAsInt8:
    136         imp->setInt8(byteOffset, static_cast<int8_t>(value), ec);
    137         break;
    138     case AccessDataViewMemberAsUint8:
    139         imp->setUint8(byteOffset, static_cast<uint8_t>(value), ec);
    140         break;
    141     default:
    142         ASSERT_NOT_REACHED();
    143         break;
    144     }
    145     setDOMException(exec, ec);
    146     return jsUndefined();
    147 }
    148 
    149 JSValue JSDataView::setInt8(ExecState* exec)
    150 {
    151     return setDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsInt8);
    152 }
    153 
    154 JSValue JSDataView::setUint8(ExecState* exec)
    155 {
    156     return setDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsUint8);
    157 }
    158 
    159 } // namespace WebCore
    160