e0918d54d3ff311c59f9c2189f395ad703830af5
[WebKit.git] / Source / JavaScriptCore / wasm / js / WebAssemblyTablePrototype.cpp
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
36 namespace JSC {
37 static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncLength(ExecState*);
38 static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGrow(ExecState*);
39 static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGet(ExecState*);
40 static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncSet(ExecState*);
41 }
42
43 #include "WebAssemblyTablePrototype.lut.h"
44
45 namespace JSC {
46
47 const 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
58 static 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
70 static 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
80 static 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
99 static 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     if (JSObject* result = table->getFunction(index))
113         return JSValue::encode(result);
114     return JSValue::encode(jsNull());
115 }
116
117 static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncSet(ExecState* exec)
118 {
119     VM& vm = exec->vm();
120     auto throwScope = DECLARE_THROW_SCOPE(vm);
121
122     JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
123     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
124
125     JSValue value = exec->argument(1);
126     WebAssemblyFunction* wasmFunction;
127     WebAssemblyWrapperFunction* wasmWrapperFunction;
128     if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction))
129         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)));
130
131     uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
132     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
133
134     if (index >= table->length())
135         return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.set expects an integer less than the length of the table"_s)));
136
137     if (value.isNull())
138         table->clearFunction(index);
139     else {
140         ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
141         ASSERT(!!wasmFunction || !!wasmWrapperFunction);
142         if (wasmFunction)
143             table->setFunction(vm, index, wasmFunction);
144         else
145             table->setFunction(vm, index, wasmWrapperFunction);
146     }
147     
148     return JSValue::encode(jsUndefined());
149 }
150
151 WebAssemblyTablePrototype* WebAssemblyTablePrototype::create(VM& vm, JSGlobalObject*, Structure* structure)
152 {
153     auto* object = new (NotNull, allocateCell<WebAssemblyTablePrototype>(vm.heap)) WebAssemblyTablePrototype(vm, structure);
154     object->finishCreation(vm);
155     return object;
156 }
157
158 Structure* WebAssemblyTablePrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
159 {
160     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
161 }
162
163 void WebAssemblyTablePrototype::finishCreation(VM& vm)
164 {
165     Base::finishCreation(vm);
166     ASSERT(inherits(vm, info()));
167     didBecomePrototype();
168 }
169
170 WebAssemblyTablePrototype::WebAssemblyTablePrototype(VM& vm, Structure* structure)
171     : Base(vm, structure)
172 {
173 }
174
175 } // namespace JSC
176
177 #endif // ENABLE(WEBASSEMBLY)