[JSC] Add @@toStringTag to WebAssembly.Global
[WebKit.git] / Source / JavaScriptCore / wasm / js / WebAssemblyGlobalPrototype.cpp
1 /*
2  * Copyright (C) 2019-2020 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 "WebAssemblyGlobalPrototype.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "FunctionPrototype.h"
32 #include "GetterSetter.h"
33 #include "IntegrityInlines.h"
34 #include "JSCInlines.h"
35 #include "JSWebAssemblyGlobal.h"
36 #include "JSWebAssemblyHelpers.h"
37
38 namespace JSC {
39 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoFuncValueOf(JSGlobalObject*, CallFrame*);
40 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoGetterFuncValue(JSGlobalObject*, CallFrame*);
41 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoSetterFuncValue(JSGlobalObject*, CallFrame*);
42 }
43
44 #include "WebAssemblyGlobalPrototype.lut.h"
45
46 namespace JSC {
47
48 const ClassInfo WebAssemblyGlobalPrototype::s_info = { "WebAssembly.Global", &Base::s_info, &prototypeGlobalWebAssemblyGlobal, nullptr, CREATE_METHOD_TABLE(WebAssemblyGlobalPrototype) };
49
50 /* Source for WebAssemblyGlobalPrototype.lut.h
51  @begin prototypeGlobalWebAssemblyGlobal
52  valueOf webAssemblyGlobalProtoFuncValueOf Function 0
53  @end
54  */
55
56 static ALWAYS_INLINE JSWebAssemblyGlobal* getGlobal(JSGlobalObject* globalObject, VM& vm, JSValue v)
57 {
58     auto throwScope = DECLARE_THROW_SCOPE(vm);
59     JSWebAssemblyGlobal* result = jsDynamicCast<JSWebAssemblyGlobal*>(vm, v);
60     if (!result) {
61         throwException(globalObject, throwScope,
62             createTypeError(globalObject, "expected |this| value to be an instance of WebAssembly.Global"_s));
63         return nullptr;
64     }
65     Integrity::auditStructureID(vm, result->structureID());
66     return result;
67 }
68
69 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoFuncValueOf(JSGlobalObject* globalObject, CallFrame* callFrame)
70 {
71     VM& vm = globalObject->vm();
72     auto throwScope = DECLARE_THROW_SCOPE(vm);
73
74     JSWebAssemblyGlobal* global = getGlobal(globalObject, vm, callFrame->thisValue());
75     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
76
77     switch (global->global()->type()) {
78     case Wasm::Type::I64:
79         return JSValue::encode(throwException(globalObject, throwScope, createTypeError(globalObject, "WebAssembly.Global.prototype.valueOf does not work with i64 type"_s)));
80     default:
81         return JSValue::encode(global->global()->get());
82     }
83 }
84
85 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoGetterFuncValue(JSGlobalObject* globalObject, CallFrame* callFrame)
86 {
87     VM& vm = globalObject->vm();
88     auto throwScope = DECLARE_THROW_SCOPE(vm);
89
90     JSWebAssemblyGlobal* global = getGlobal(globalObject, vm, callFrame->thisValue());
91     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
92
93     switch (global->global()->type()) {
94     case Wasm::Type::I64:
95         return JSValue::encode(throwException(globalObject, throwScope, createTypeError(globalObject, "WebAssembly.Global.prototype.value does not work with i64 type"_s)));
96     default:
97         return JSValue::encode(global->global()->get());
98     }
99 }
100
101 static EncodedJSValue JSC_HOST_CALL webAssemblyGlobalProtoSetterFuncValue(JSGlobalObject* globalObject, CallFrame* callFrame)
102 {
103     VM& vm = globalObject->vm();
104     auto throwScope = DECLARE_THROW_SCOPE(vm);
105
106     if (UNLIKELY(callFrame->argumentCount() < 1))
107         return JSValue::encode(throwException(globalObject, throwScope, createNotEnoughArgumentsError(globalObject)));
108
109     JSWebAssemblyGlobal* global = getGlobal(globalObject, vm, callFrame->thisValue());
110     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
111
112     if (global->global()->mutability() == Wasm::GlobalInformation::Mutability::Immutable)
113         return JSValue::encode(throwException(globalObject, throwScope, createTypeError(globalObject, "WebAssembly.Global.prototype.value attempts to modify immutable global value"_s)));
114
115     switch (global->global()->type()) {
116     case Wasm::Type::I64:
117         return JSValue::encode(throwException(globalObject, throwScope, createTypeError(globalObject, "WebAssembly.Global.prototype.value does not work with i64 type"_s)));
118     default:
119         global->global()->set(globalObject, callFrame->argument(0));
120         RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
121         return JSValue::encode(jsUndefined());
122     }
123 }
124
125 WebAssemblyGlobalPrototype* WebAssemblyGlobalPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
126 {
127     auto* object = new (NotNull, allocateCell<WebAssemblyGlobalPrototype>(vm.heap)) WebAssemblyGlobalPrototype(vm, structure);
128     object->finishCreation(vm, globalObject);
129     return object;
130 }
131
132 Structure* WebAssemblyGlobalPrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
133 {
134     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
135 }
136
137 void WebAssemblyGlobalPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
138 {
139     Base::finishCreation(vm);
140     ASSERT(inherits(vm, info()));
141
142     JSFunction* valueGetterFunction = JSFunction::create(vm, globalObject, 0, "get value"_s, webAssemblyGlobalProtoGetterFuncValue, NoIntrinsic);
143     JSFunction* valueSetterFunction = JSFunction::create(vm, globalObject, 1, "set value"_s, webAssemblyGlobalProtoSetterFuncValue, NoIntrinsic);
144     GetterSetter* valueAccessor = GetterSetter::create(vm, globalObject, valueGetterFunction, valueSetterFunction);
145     putDirectNonIndexAccessorWithoutTransition(vm, Identifier::fromString(vm, "value"_s), valueAccessor, static_cast<unsigned>(PropertyAttribute::Accessor));
146     JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
147 }
148
149 WebAssemblyGlobalPrototype::WebAssemblyGlobalPrototype(VM& vm, Structure* structure)
150     : Base(vm, structure)
151 {
152 }
153
154 } // namespace JSC
155
156 #endif // ENABLE(WEBASSEMBLY)