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
toJS(ExecState * exec,JSDOMGlobalObject * globalObject,DataView * object)45 JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, DataView* object)
46 {
47 return wrap<JSDataView>(exec, globalObject, object);
48 }
49
constructJSDataView(ExecState * exec)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
getDataViewMember(ExecState * exec,DataView * imp,DataViewAccessType type)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
getInt8(ExecState * exec)102 JSValue JSDataView::getInt8(ExecState* exec)
103 {
104 return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsInt8);
105 }
106
getUint8(ExecState * exec)107 JSValue JSDataView::getUint8(ExecState* exec)
108 {
109 return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsUint8);
110 }
111
getFloat32(ExecState * exec)112 JSValue JSDataView::getFloat32(ExecState* exec)
113 {
114 return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsFloat32);
115 }
116
getFloat64(ExecState * exec)117 JSValue JSDataView::getFloat64(ExecState* exec)
118 {
119 return getDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsFloat64);
120 }
121
setDataViewMember(ExecState * exec,DataView * imp,DataViewAccessType type)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
setInt8(ExecState * exec)149 JSValue JSDataView::setInt8(ExecState* exec)
150 {
151 return setDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsInt8);
152 }
153
setUint8(ExecState * exec)154 JSValue JSDataView::setUint8(ExecState* exec)
155 {
156 return setDataViewMember(exec, static_cast<DataView*>(impl()), AccessDataViewMemberAsUint8);
157 }
158
159 } // namespace WebCore
160