1/*
2 * Copyright (C) 2016-2018 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 "WebAssemblyTablePrototype.h"
28
29#if ENABLE(WEBASSEMBLY)
30
31#include "FunctionPrototype.h"
32#include "JSCInlines.h"
33#include "JSWebAssemblyHelpers.h"
34#include "JSWebAssemblyTable.h"
35
36namespace JSC {
37static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncLength(ExecState*);
38static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGrow(ExecState*);
39static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGet(ExecState*);
40static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncSet(ExecState*);
41}
42
43#include "WebAssemblyTablePrototype.lut.h"
44
45namespace JSC {
46
47const ClassInfo WebAssemblyTablePrototype::s_info = { "WebAssembly.Table", &Base::s_info, &prototypeTableWebAssemblyTable, nullptr, CREATE_METHOD_TABLE(WebAssemblyTablePrototype) };
48
49/* Source for WebAssemblyTablePrototype.lut.h
50 @begin prototypeTableWebAssemblyTable
51 length webAssemblyTableProtoFuncLength DontEnum|Accessor 0
52 grow webAssemblyTableProtoFuncGrow DontEnum|Function 1
53 get webAssemblyTableProtoFuncGet DontEnum|Function 1
54 set webAssemblyTableProtoFuncSet DontEnum|Function 2
55 @end
56 */
57
58static ALWAYS_INLINE JSWebAssemblyTable* getTable(ExecState* exec, VM& vm, JSValue v)
59{
60 auto throwScope = DECLARE_THROW_SCOPE(vm);
61 JSWebAssemblyTable* result = jsDynamicCast<JSWebAssemblyTable*>(vm, v);
62 if (!result) {
63 throwException(exec, throwScope,
64 createTypeError(exec, "expected |this| value to be an instance of WebAssembly.Table"_s));
65 return nullptr;
66 }
67 return result;
68}
69
70static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncLength(ExecState* exec)
71{
72 VM& vm = exec->vm();
73 auto throwScope = DECLARE_THROW_SCOPE(vm);
74
75 JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
76 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
77 return JSValue::encode(jsNumber(table->length()));
78}
79
80static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGrow(ExecState* exec)
81{
82 VM& vm = exec->vm();
83 auto throwScope = DECLARE_THROW_SCOPE(vm);
84
85 JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
86 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
87
88 uint32_t delta = toNonWrappingUint32(exec, exec->argument(0));
89 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
90
91 uint32_t oldLength = table->length();
92
93 if (!table->grow(delta))
94 return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.grow could not grow the table"_s)));
95
96 return JSValue::encode(jsNumber(oldLength));
97}
98
99static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGet(ExecState* exec)
100{
101 VM& vm = exec->vm();
102 auto throwScope = DECLARE_THROW_SCOPE(vm);
103
104 JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
105 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
106
107 uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
108 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
109 if (index >= table->length())
110 return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.get expects an integer less than the length of the table"_s)));
111
112 return JSValue::encode(table->get(index));
113}
114
115static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncSet(ExecState* exec)
116{
117 VM& vm = exec->vm();
118 auto throwScope = DECLARE_THROW_SCOPE(vm);
119
120 JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
121 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
122
123 JSValue value = exec->argument(1);
124
125 uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
126 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
127
128 if (index >= table->length())
129 return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.set expects an integer less than the length of the table"_s)));
130
131 if (table->table()->asFuncrefTable()) {
132 WebAssemblyFunction* wasmFunction;
133 WebAssemblyWrapperFunction* wasmWrapperFunction;
134 if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction))
135 return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, "WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function"_s)));
136
137 if (value.isNull())
138 table->clear(index);
139 else {
140 ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
141 ASSERT(!!wasmFunction || !!wasmWrapperFunction);
142 if (wasmFunction)
143 table->set(index, wasmFunction);
144 else
145 table->set(index, wasmWrapperFunction);
146 }
147 } else
148 table->set(index, value);
149
150 return JSValue::encode(jsUndefined());
151}
152
153WebAssemblyTablePrototype* WebAssemblyTablePrototype::create(VM& vm, JSGlobalObject*, Structure* structure)
154{
155 auto* object = new (NotNull, allocateCell<WebAssemblyTablePrototype>(vm.heap)) WebAssemblyTablePrototype(vm, structure);
156 object->finishCreation(vm);
157 return object;
158}
159
160Structure* WebAssemblyTablePrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
161{
162 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
163}
164
165void WebAssemblyTablePrototype::finishCreation(VM& vm)
166{
167 Base::finishCreation(vm);
168 ASSERT(inherits(vm, info()));
169}
170
171WebAssemblyTablePrototype::WebAssemblyTablePrototype(VM& vm, Structure* structure)
172 : Base(vm, structure)
173{
174}
175
176} // namespace JSC
177
178#endif // ENABLE(WEBASSEMBLY)
179