Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/api-natives.h"
6 : #include "src/api.h"
7 : #include "src/assert-scope.h"
8 : #include "src/ast/ast.h"
9 : #include "src/execution.h"
10 : #include "src/factory.h"
11 : #include "src/handles.h"
12 : #include "src/isolate.h"
13 : #include "src/objects-inl.h"
14 : #include "src/objects.h"
15 : #include "src/parsing/parse-info.h"
16 :
17 : #include "src/wasm/module-compiler.h"
18 : #include "src/wasm/module-decoder.h"
19 : #include "src/wasm/wasm-api.h"
20 : #include "src/wasm/wasm-js.h"
21 : #include "src/wasm/wasm-limits.h"
22 : #include "src/wasm/wasm-memory.h"
23 : #include "src/wasm/wasm-module.h"
24 : #include "src/wasm/wasm-objects-inl.h"
25 : #include "src/wasm/wasm-result.h"
26 :
27 : using v8::internal::wasm::ErrorThrower;
28 :
29 : namespace v8 {
30 :
31 : namespace {
32 :
33 : #define ASSIGN(type, var, expr) \
34 : Local<type> var; \
35 : do { \
36 : if (!expr.ToLocal(&var)) { \
37 : DCHECK(i_isolate->has_scheduled_exception()); \
38 : return; \
39 : } else { \
40 : DCHECK(!i_isolate->has_scheduled_exception()); \
41 : } \
42 : } while (false)
43 :
44 : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
45 1824897 : return isolate->factory()->NewStringFromAsciiChecked(str);
46 : }
47 : Local<String> v8_str(Isolate* isolate, const char* str) {
48 : return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
49 : }
50 :
51 147708 : i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule(
52 : const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
53 : i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);
54 147708 : if (!arg0->IsWasmModuleObject()) {
55 300 : thrower->TypeError("Argument 0 must be a WebAssembly.Module");
56 300 : return {};
57 : }
58 :
59 : Local<Object> module_obj = Local<Object>::Cast(args[0]);
60 : return i::Handle<i::WasmModuleObject>::cast(
61 147408 : v8::Utils::OpenHandle(*module_obj));
62 : }
63 :
64 304611 : i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
65 304611 : const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
66 : const uint8_t* start = nullptr;
67 : size_t length = 0;
68 : v8::Local<v8::Value> source = args[0];
69 304611 : if (source->IsArrayBuffer()) {
70 : // A raw array buffer was passed.
71 : Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
72 303761 : ArrayBuffer::Contents contents = buffer->GetContents();
73 :
74 303761 : start = reinterpret_cast<const uint8_t*>(contents.Data());
75 303761 : length = contents.ByteLength();
76 850 : } else if (source->IsTypedArray()) {
77 : // A TypedArray was passed.
78 : Local<TypedArray> array = Local<TypedArray>::Cast(source);
79 530 : Local<ArrayBuffer> buffer = array->Buffer();
80 :
81 530 : ArrayBuffer::Contents contents = buffer->GetContents();
82 :
83 : start =
84 530 : reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
85 530 : length = array->ByteLength();
86 : } else {
87 320 : thrower->TypeError("Argument 0 must be a buffer source");
88 : }
89 : DCHECK_IMPLIES(length, start != nullptr);
90 304611 : if (length == 0) {
91 620 : thrower->CompileError("BufferSource argument is empty");
92 : }
93 304611 : if (length > i::wasm::kV8MaxWasmModuleSize) {
94 : thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
95 10 : i::wasm::kV8MaxWasmModuleSize, length);
96 : }
97 304611 : if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
98 607942 : return i::wasm::ModuleWireBytes(start, start + length);
99 : }
100 :
101 147718 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
102 : ErrorThrower* thrower) {
103 147718 : if (arg->IsUndefined()) return {};
104 :
105 144364 : if (!arg->IsObject()) {
106 150 : thrower->TypeError("Argument 1 must be an object");
107 150 : return {};
108 : }
109 : Local<Object> obj = Local<Object>::Cast(arg);
110 144214 : return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
111 : }
112 :
113 0 : void WebAssemblyCompileStreaming(
114 0 : const v8::FunctionCallbackInfo<v8::Value>& args) {
115 : v8::Isolate* isolate = args.GetIsolate();
116 0 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
117 :
118 0 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
119 : // Manually create a promise and reject it.
120 0 : Local<Context> context = isolate->GetCurrentContext();
121 0 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
122 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
123 0 : return_value.Set(resolver->GetPromise());
124 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
125 : "WebAssembly.compileStreaming()");
126 0 : thrower.CompileError("Wasm code generation disallowed by embedder");
127 0 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
128 0 : CHECK_IMPLIES(!maybe.FromMaybe(false),
129 : i_isolate->has_scheduled_exception());
130 0 : return;
131 : }
132 :
133 0 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
134 : DCHECK_NOT_NULL(i_isolate->wasm_compile_streaming_callback());
135 0 : i_isolate->wasm_compile_streaming_callback()(args);
136 : }
137 :
138 : // WebAssembly.compile(bytes) -> Promise
139 2160 : void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
140 : v8::Isolate* isolate = args.GetIsolate();
141 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
142 1080 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
143 :
144 1870 : HandleScope scope(isolate);
145 790 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
146 :
147 1080 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
148 10 : thrower.CompileError("Wasm code generation disallowed by embedder");
149 : }
150 :
151 1080 : Local<Context> context = isolate->GetCurrentContext();
152 2450 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
153 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
154 1080 : return_value.Set(resolver->GetPromise());
155 :
156 1080 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
157 1080 : if (thrower.error()) {
158 290 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
159 290 : CHECK_IMPLIES(!maybe.FromMaybe(false),
160 : i_isolate->has_scheduled_exception());
161 : return;
162 : }
163 1580 : i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise());
164 1580 : i::wasm::AsyncCompile(i_isolate, promise, bytes);
165 : }
166 :
167 : // WebAssembly.validate(bytes) -> bool
168 294940 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
169 : v8::Isolate* isolate = args.GetIsolate();
170 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
171 147470 : HandleScope scope(isolate);
172 147470 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
173 :
174 147470 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
175 :
176 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
177 294860 : if (!thrower.error() &&
178 147390 : i::wasm::SyncValidate(reinterpret_cast<i::Isolate*>(isolate), bytes)) {
179 : return_value.Set(v8::True(isolate));
180 : } else {
181 24800 : if (thrower.wasm_error()) thrower.Reset(); // Clear error.
182 : return_value.Set(v8::False(isolate));
183 147470 : }
184 147470 : }
185 :
186 : // new WebAssembly.Module(bytes) -> WebAssembly.Module
187 299492 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
188 : v8::Isolate* isolate = args.GetIsolate();
189 156081 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
190 168751 : if (i_isolate->wasm_module_callback()(args)) return;
191 :
192 156071 : HandleScope scope(isolate);
193 143411 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
194 :
195 156071 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
196 10 : thrower.CompileError("Wasm code generation disallowed by embedder");
197 10 : return;
198 : }
199 :
200 156061 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
201 :
202 156061 : if (thrower.error()) {
203 : return;
204 : }
205 : i::MaybeHandle<i::Object> module_obj =
206 155791 : i::wasm::SyncCompile(i_isolate, &thrower, bytes);
207 155791 : if (module_obj.is_null()) return;
208 :
209 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
210 143411 : return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
211 : }
212 :
213 : // WebAssembly.Module.imports(module) -> Array<Import>
214 240 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
215 100 : HandleScope scope(args.GetIsolate());
216 : v8::Isolate* isolate = args.GetIsolate();
217 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
218 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
219 40 : "WebAssembly.Module.imports()");
220 :
221 100 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
222 160 : if (thrower.error()) return;
223 40 : auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
224 40 : args.GetReturnValue().Set(Utils::ToLocal(imports));
225 : }
226 :
227 : // WebAssembly.Module.exports(module) -> Array<Export>
228 240 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
229 100 : HandleScope scope(args.GetIsolate());
230 : v8::Isolate* isolate = args.GetIsolate();
231 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
232 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
233 40 : "WebAssembly.Module.exports()");
234 :
235 100 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
236 160 : if (thrower.error()) return;
237 40 : auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
238 40 : args.GetReturnValue().Set(Utils::ToLocal(exports));
239 : }
240 :
241 : // WebAssembly.Module.customSections(module, name) -> Array<Section>
242 140 : void WebAssemblyModuleCustomSections(
243 340 : const v8::FunctionCallbackInfo<v8::Value>& args) {
244 140 : HandleScope scope(args.GetIsolate());
245 : v8::Isolate* isolate = args.GetIsolate();
246 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
247 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
248 60 : "WebAssembly.Module.customSections()");
249 :
250 140 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
251 220 : if (thrower.error()) return;
252 :
253 : i::MaybeHandle<i::Object> maybe_name =
254 70 : i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
255 : i::Handle<i::Object> name;
256 70 : if (!maybe_name.ToHandle(&name)) return;
257 : auto custom_sections =
258 : i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
259 60 : i::Handle<i::String>::cast(name), &thrower);
260 60 : if (thrower.error()) return;
261 60 : args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
262 : }
263 :
264 147718 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
265 : Local<Value> module,
266 : Local<Value> ffi) {
267 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
268 :
269 : i::MaybeHandle<i::Object> instance_object;
270 : {
271 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
272 : "WebAssembly Instantiation");
273 : i::MaybeHandle<i::JSReceiver> maybe_imports =
274 147718 : GetValueAsImports(ffi, &thrower);
275 147718 : if (thrower.error()) return {};
276 :
277 : i::Handle<i::WasmModuleObject> module_obj =
278 : i::Handle<i::WasmModuleObject>::cast(
279 147568 : Utils::OpenHandle(Object::Cast(*module)));
280 : instance_object =
281 : i::wasm::SyncInstantiate(i_isolate, &thrower, module_obj, maybe_imports,
282 147568 : i::MaybeHandle<i::JSArrayBuffer>());
283 : }
284 :
285 : DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
286 147568 : if (instance_object.is_null()) return {};
287 146118 : return Utils::ToLocal(instance_object.ToHandleChecked());
288 : }
289 :
290 : // Entered as internal implementation detail of sync and async instantiate.
291 : // args[0] *must* be a WebAssembly.Module.
292 110 : void WebAssemblyInstantiateImplCallback(
293 380 : const v8::FunctionCallbackInfo<v8::Value>& args) {
294 : DCHECK_GE(args.Length(), 1);
295 : v8::Isolate* isolate = args.GetIsolate();
296 : MicrotasksScope does_not_run_microtasks(isolate,
297 110 : MicrotasksScope::kDoNotRunMicrotasks);
298 :
299 220 : HandleScope scope(args.GetIsolate());
300 110 : Local<Value> module = args[0];
301 110 : Local<Value> ffi = args.Data();
302 : Local<Value> instance;
303 220 : if (WebAssemblyInstantiateImpl(isolate, module, ffi).ToLocal(&instance)) {
304 : args.GetReturnValue().Set(instance);
305 110 : }
306 110 : }
307 :
308 350 : void WebAssemblyInstantiateToPairCallback(
309 1190 : const v8::FunctionCallbackInfo<v8::Value>& args) {
310 : DCHECK_GE(args.Length(), 1);
311 : Isolate* isolate = args.GetIsolate();
312 : MicrotasksScope does_not_run_microtasks(isolate,
313 350 : MicrotasksScope::kDoNotRunMicrotasks);
314 :
315 490 : HandleScope scope(args.GetIsolate());
316 :
317 350 : Local<Context> context = isolate->GetCurrentContext();
318 350 : Local<Value> module = args[0];
319 :
320 : const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
321 : const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
322 : Local<Value> instance;
323 350 : if (!WebAssemblyInstantiateImpl(isolate, module, args.Data())
324 350 : .ToLocal(&instance)) {
325 210 : return;
326 : }
327 :
328 140 : Local<Object> ret = Object::New(isolate);
329 : Local<String> instance_name =
330 : String::NewFromOneByte(isolate, instance_str,
331 : NewStringType::kInternalized)
332 140 : .ToLocalChecked();
333 : Local<String> module_name =
334 : String::NewFromOneByte(isolate, module_str, NewStringType::kInternalized)
335 140 : .ToLocalChecked();
336 :
337 140 : CHECK(ret->CreateDataProperty(context, instance_name, instance).IsJust());
338 140 : CHECK(ret->CreateDataProperty(context, module_name, module).IsJust());
339 140 : args.GetReturnValue().Set(ret);
340 : }
341 :
342 : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
343 440684 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
344 : Isolate* isolate = args.GetIsolate();
345 : MicrotasksScope does_not_run_microtasks(isolate,
346 147378 : MicrotasksScope::kDoNotRunMicrotasks);
347 :
348 294636 : HandleScope scope(args.GetIsolate());
349 147378 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
350 147498 : if (i_isolate->wasm_instance_callback()(args)) return;
351 :
352 147258 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
353 :
354 147368 : GetFirstArgumentAsModule(args, &thrower);
355 147478 : if (thrower.error()) return;
356 :
357 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
358 : // We'll check for that in WebAssemblyInstantiateImpl.
359 147258 : Local<Value> data = args[1];
360 :
361 : Local<Value> instance;
362 294516 : if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
363 : args.GetReturnValue().Set(instance);
364 147258 : }
365 : }
366 :
367 0 : void WebAssemblyInstantiateStreaming(
368 0 : const v8::FunctionCallbackInfo<v8::Value>& args) {
369 : v8::Isolate* isolate = args.GetIsolate();
370 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
371 : // we use i_isolate in DCHECKS in the ASSIGN statements.
372 : USE(i_isolate);
373 0 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
374 0 : HandleScope scope(isolate);
375 :
376 0 : Local<Context> context = isolate->GetCurrentContext();
377 0 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
378 0 : Local<Value> first_arg_value = args[0];
379 :
380 0 : ASSIGN(Function, compileStreaming,
381 : Function::New(context, WebAssemblyCompileStreaming));
382 0 : ASSIGN(Value, compile_retval,
383 : compileStreaming->Call(context, args.Holder(), 1, &first_arg_value));
384 : Local<Promise> module_promise = Local<Promise>::Cast(compile_retval);
385 :
386 : DCHECK(!module_promise.IsEmpty());
387 0 : Local<Value> data = args[1];
388 0 : ASSIGN(Function, instantiate_impl,
389 : Function::New(context, WebAssemblyInstantiateToPairCallback, data));
390 0 : ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
391 0 : args.GetReturnValue().Set(result);
392 : }
393 :
394 : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
395 : // WebAssembly.instantiate(bytes, imports) ->
396 : // {module: WebAssembly.Module, instance: WebAssembly.Instance}
397 16424 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
398 : v8::Isolate* isolate = args.GetIsolate();
399 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
400 7722 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
401 :
402 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
403 550 : "WebAssembly.instantiate()");
404 :
405 8272 : HandleScope scope(isolate);
406 :
407 7722 : Local<Context> context = isolate->GetCurrentContext();
408 :
409 22616 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
410 7712 : Local<Promise> module_promise = resolver->GetPromise();
411 : args.GetReturnValue().Set(module_promise);
412 :
413 7712 : Local<Value> first_arg_value = args[0];
414 : i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
415 7712 : if (!first_arg->IsJSObject()) {
416 : thrower.TypeError(
417 7162 : "Argument 0 must be a buffer source or a WebAssembly.Module object");
418 7162 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
419 7162 : CHECK_IMPLIES(!maybe.FromMaybe(false),
420 : i_isolate->has_scheduled_exception());
421 : return;
422 : }
423 :
424 : FunctionCallback instantiator = nullptr;
425 550 : if (first_arg->IsWasmModuleObject()) {
426 110 : module_promise = resolver->GetPromise();
427 110 : if (!resolver->Resolve(context, first_arg_value).IsJust()) return;
428 : instantiator = WebAssemblyInstantiateImplCallback;
429 : } else {
430 880 : ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
431 880 : ASSIGN(Value, async_compile_retval,
432 : async_compile->Call(context, args.Holder(), 1, &first_arg_value));
433 : module_promise = Local<Promise>::Cast(async_compile_retval);
434 : instantiator = WebAssemblyInstantiateToPairCallback;
435 : }
436 : DCHECK(!module_promise.IsEmpty());
437 : DCHECK_NOT_NULL(instantiator);
438 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
439 : // We'll check for that in WebAssemblyInstantiateImpl.
440 550 : Local<Value> data = args[1];
441 1100 : ASSIGN(Function, instantiate_impl,
442 : Function::New(context, instantiator, data));
443 1100 : ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
444 550 : args.GetReturnValue().Set(result);
445 : }
446 :
447 5200 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
448 : Local<Context> context, Local<v8::Object> object,
449 : Local<String> property, int64_t* result,
450 : int64_t lower_bound, uint64_t upper_bound) {
451 5200 : v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
452 : v8::Local<v8::Value> value;
453 5200 : if (maybe.ToLocal(&value)) {
454 : int64_t number;
455 10400 : if (!value->IntegerValue(context).To(&number)) return false;
456 5160 : if (number < lower_bound) {
457 : thrower->RangeError("Property value %" PRId64
458 : " is below the lower bound %" PRIx64,
459 160 : number, lower_bound);
460 : return false;
461 : }
462 5000 : if (number > static_cast<int64_t>(upper_bound)) {
463 : thrower->RangeError("Property value %" PRId64
464 : " is above the upper bound %" PRIu64,
465 130 : number, upper_bound);
466 : return false;
467 : }
468 4870 : *result = static_cast<int>(number);
469 : return true;
470 : }
471 : return false;
472 : }
473 :
474 : // new WebAssembly.Table(args) -> WebAssembly.Table
475 2990 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
476 : v8::Isolate* isolate = args.GetIsolate();
477 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
478 1660 : HandleScope scope(isolate);
479 1330 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
480 1660 : if (!args[0]->IsObject()) {
481 70 : thrower.TypeError("Argument 0 must be a table descriptor");
482 70 : return;
483 : }
484 1590 : Local<Context> context = isolate->GetCurrentContext();
485 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
486 : // The descriptor's 'element'.
487 : {
488 : v8::MaybeLocal<v8::Value> maybe =
489 1590 : descriptor->Get(context, v8_str(isolate, "element"));
490 : v8::Local<v8::Value> value;
491 1590 : if (!maybe.ToLocal(&value)) return;
492 : v8::Local<v8::String> string;
493 3180 : if (!value->ToString(context).ToLocal(&string)) return;
494 : bool equal;
495 3180 : if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return;
496 1590 : if (!equal) {
497 110 : thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
498 110 : return;
499 : }
500 : }
501 : // The descriptor's 'initial'.
502 1480 : int64_t initial = 0;
503 1480 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
504 : v8_str(isolate, "initial"), &initial, 0,
505 2960 : i::FLAG_wasm_max_table_size)) {
506 : return;
507 : }
508 : // The descriptor's 'maximum'.
509 1400 : int64_t maximum = -1;
510 : Local<String> maximum_key = v8_str(isolate, "maximum");
511 1400 : Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
512 :
513 2800 : if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
514 1080 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
515 : &maximum, initial,
516 1080 : i::wasm::kSpecMaxWasmTableSize)) {
517 : return;
518 : }
519 : }
520 :
521 : i::Handle<i::FixedArray> fixed_array;
522 : i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
523 1330 : i_isolate, static_cast<uint32_t>(initial), maximum, &fixed_array);
524 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
525 1330 : return_value.Set(Utils::ToLocal(table_obj));
526 : }
527 :
528 3030 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
529 : v8::Isolate* isolate = args.GetIsolate();
530 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
531 1640 : HandleScope scope(isolate);
532 1390 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
533 1640 : if (!args[0]->IsObject()) {
534 70 : thrower.TypeError("Argument 0 must be a memory descriptor");
535 70 : return;
536 : }
537 1570 : Local<Context> context = isolate->GetCurrentContext();
538 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
539 : // The descriptor's 'initial'.
540 1570 : int64_t initial = 0;
541 1570 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
542 : v8_str(isolate, "initial"), &initial, 0,
543 3140 : i::FLAG_wasm_max_mem_pages)) {
544 : return;
545 : }
546 : // The descriptor's 'maximum'.
547 1480 : int64_t maximum = -1;
548 : Local<String> maximum_key = v8_str(isolate, "maximum");
549 1480 : Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
550 :
551 2960 : if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
552 1070 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
553 : &maximum, initial,
554 1070 : i::wasm::kSpecMaxWasmMemoryPages)) {
555 : return;
556 : }
557 : }
558 :
559 : bool is_shared_memory = false;
560 1390 : if (i::FLAG_experimental_wasm_threads) {
561 : // Shared property of descriptor
562 : Local<String> shared_key = v8_str(isolate, "shared");
563 150 : Maybe<bool> has_shared = descriptor->Has(context, shared_key);
564 300 : if (!has_shared.IsNothing() && has_shared.FromJust()) {
565 140 : v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, shared_key);
566 : v8::Local<v8::Value> value;
567 140 : if (maybe.ToLocal(&value)) {
568 280 : if (!value->BooleanValue(context).To(&is_shared_memory)) return;
569 : }
570 : }
571 : // Throw TypeError if shared is true, and the descriptor has no "maximum"
572 150 : if (is_shared_memory && maximum == -1) {
573 : thrower.TypeError(
574 10 : "If shared is true, maximum property should be defined.");
575 : }
576 : }
577 :
578 1390 : size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) *
579 1390 : static_cast<size_t>(initial);
580 : i::Handle<i::JSArrayBuffer> buffer = i::wasm::NewArrayBuffer(
581 : i_isolate, size, internal::trap_handler::UseTrapHandler(),
582 2780 : is_shared_memory ? i::SharedFlag::kShared : i::SharedFlag::kNotShared);
583 1390 : if (buffer.is_null()) {
584 0 : thrower.RangeError("could not allocate memory");
585 0 : return;
586 : }
587 1390 : if (buffer->is_shared()) {
588 : Maybe<bool> result =
589 110 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::Object::DONT_THROW);
590 110 : if (!result.FromJust()) {
591 : thrower.TypeError(
592 0 : "Status of setting SetIntegrityLevel of buffer is false.");
593 : }
594 : }
595 : i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New(
596 1390 : i_isolate, buffer, static_cast<int32_t>(maximum));
597 1390 : args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
598 : }
599 :
600 : constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
601 : constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
602 : constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
603 :
604 : #define EXTRACT_THIS(var, WasmType) \
605 : i::Handle<i::WasmType> var; \
606 : { \
607 : i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
608 : if (!this_arg->Is##WasmType()) { \
609 : thrower.TypeError("Receiver is not a %s", kName_##WasmType); \
610 : return; \
611 : } \
612 : var = i::Handle<i::WasmType>::cast(this_arg); \
613 : }
614 :
615 26250079 : void WebAssemblyInstanceGetExports(
616 78750199 : const v8::FunctionCallbackInfo<v8::Value>& args) {
617 : v8::Isolate* isolate = args.GetIsolate();
618 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
619 26250079 : HandleScope scope(isolate);
620 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
621 26250041 : "WebAssembly.Instance.exports()");
622 52500158 : EXTRACT_THIS(receiver, WasmInstanceObject);
623 : i::Handle<i::JSObject> exports_object(receiver->exports_object());
624 26250041 : args.GetReturnValue().Set(Utils::ToLocal(exports_object));
625 : }
626 :
627 9578 : void WebAssemblyTableGetLength(
628 28666 : const v8::FunctionCallbackInfo<v8::Value>& args) {
629 : v8::Isolate* isolate = args.GetIsolate();
630 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
631 9578 : HandleScope scope(isolate);
632 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
633 9510 : "WebAssembly.Table.length()");
634 19156 : EXTRACT_THIS(receiver, WasmTableObject);
635 : args.GetReturnValue().Set(
636 19020 : v8::Number::New(isolate, receiver->current_length()));
637 : }
638 :
639 : // WebAssembly.Table.grow(num) -> num
640 2070 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
641 : v8::Isolate* isolate = args.GetIsolate();
642 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
643 770 : HandleScope scope(isolate);
644 530 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
645 770 : Local<Context> context = isolate->GetCurrentContext();
646 770 : EXTRACT_THIS(receiver, WasmTableObject);
647 :
648 : int64_t grow_by = 0;
649 1440 : if (!args[0]->IntegerValue(context).To(&grow_by)) return;
650 : i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate);
651 : int old_size = old_array->length();
652 :
653 720 : int64_t max_size64 = receiver->maximum_length()->Number();
654 720 : if (max_size64 < 0 || max_size64 > i::FLAG_wasm_max_table_size) {
655 90 : max_size64 = i::FLAG_wasm_max_table_size;
656 : }
657 :
658 720 : if (grow_by < 0 || grow_by > max_size64 - old_size) {
659 : thrower.RangeError(grow_by < 0 ? "trying to shrink table"
660 190 : : "maximum table size exceeded");
661 190 : return;
662 : }
663 :
664 530 : int new_size = static_cast<int>(old_size + grow_by);
665 530 : receiver->Grow(i_isolate, static_cast<uint32_t>(new_size - old_size));
666 :
667 530 : if (new_size != old_size) {
668 : i::Handle<i::FixedArray> new_array =
669 470 : i_isolate->factory()->NewFixedArray(new_size);
670 5998370 : for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i));
671 470 : i::Object* null = i_isolate->heap()->null_value();
672 106619140 : for (int i = old_size; i < new_size; ++i) new_array->set(i, null);
673 470 : receiver->set_functions(*new_array);
674 : }
675 :
676 : // TODO(gdeepti): use weak links for instances
677 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
678 530 : return_value.Set(old_size);
679 : }
680 :
681 : // WebAssembly.Table.get(num) -> JSFunction
682 32530 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
683 : v8::Isolate* isolate = args.GetIsolate();
684 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
685 10870 : HandleScope scope(isolate);
686 10620 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
687 10870 : Local<Context> context = isolate->GetCurrentContext();
688 10870 : EXTRACT_THIS(receiver, WasmTableObject);
689 : i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
690 : int64_t i = 0;
691 21640 : if (!args[0]->IntegerValue(context).To(&i)) return;
692 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
693 21550 : if (i < 0 || i >= array->length()) {
694 170 : thrower.RangeError("index out of bounds");
695 170 : return;
696 : }
697 :
698 10620 : i::Handle<i::Object> value(array->get(static_cast<int>(i)), i_isolate);
699 10620 : return_value.Set(Utils::ToLocal(value));
700 : }
701 :
702 : // WebAssembly.Table.set(num, JSFunction)
703 9180 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
704 : v8::Isolate* isolate = args.GetIsolate();
705 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
706 4590 : HandleScope scope(isolate);
707 3750 : i::wasm::ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
708 4590 : Local<Context> context = isolate->GetCurrentContext();
709 4590 : EXTRACT_THIS(receiver, WasmTableObject);
710 :
711 : // Parameter 0.
712 : int64_t index;
713 9060 : if (!args[0]->IntegerValue(context).To(&index)) return;
714 :
715 : // Parameter 1.
716 : i::Handle<i::Object> value = Utils::OpenHandle(*args[1]);
717 : // TODO(titzer): use WasmExportedFunction::IsWasmExportedFunction() here.
718 11780 : if (!value->IsNull(i_isolate) &&
719 2600 : (!value->IsJSFunction() ||
720 : i::Handle<i::JSFunction>::cast(value)->code()->kind() !=
721 : i::Code::JS_TO_WASM_FUNCTION)) {
722 260 : thrower.TypeError("Argument 1 must be null or a WebAssembly function");
723 260 : return;
724 : }
725 :
726 8410 : if (index < 0 || index >= receiver->functions()->length()) {
727 480 : thrower.RangeError("index out of bounds");
728 480 : return;
729 : }
730 :
731 : i::WasmTableObject::Set(i_isolate, receiver, static_cast<int32_t>(index),
732 : value->IsNull(i_isolate)
733 : ? i::Handle<i::JSFunction>::null()
734 7500 : : i::Handle<i::JSFunction>::cast(value));
735 : }
736 :
737 : // WebAssembly.Memory.grow(num) -> num
738 1370 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
739 : v8::Isolate* isolate = args.GetIsolate();
740 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
741 520 : HandleScope scope(isolate);
742 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
743 330 : "WebAssembly.Memory.grow()");
744 520 : Local<Context> context = isolate->GetCurrentContext();
745 520 : EXTRACT_THIS(receiver, WasmMemoryObject);
746 :
747 : int64_t delta_size = 0;
748 960 : if (!args[0]->IntegerValue(context).To(&delta_size)) return;
749 :
750 470 : int64_t max_size64 = receiver->maximum_pages();
751 830 : if (max_size64 < 0 ||
752 360 : max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) {
753 110 : max_size64 = i::FLAG_wasm_max_mem_pages;
754 : }
755 : i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer());
756 : uint32_t old_size =
757 470 : old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages;
758 470 : int64_t new_size64 = old_size + delta_size;
759 470 : if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) {
760 : thrower.RangeError(new_size64 < old_size ? "trying to shrink memory"
761 140 : : "maximum memory size exceeded");
762 140 : return;
763 : }
764 : int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver,
765 330 : static_cast<uint32_t>(delta_size));
766 330 : if (ret == -1) {
767 0 : thrower.RangeError("Unable to grow instance memory.");
768 0 : return;
769 : }
770 330 : if (!old_buffer->is_shared()) {
771 : // When delta_size == 0, or guard pages are enabled, the same backing store
772 : // is used. To be spec compliant, the buffer associated with the memory
773 : // object needs to be detached. Setup a new buffer with the same backing
774 : // store, detach the old buffer, and do not free backing store memory.
775 590 : bool free_memory = delta_size != 0 && !old_buffer->has_guard_region();
776 330 : if ((!free_memory && old_size != 0) || new_size64 == 0) {
777 : i::WasmMemoryObject::SetupNewBufferWithSameBackingStore(
778 95 : i_isolate, receiver, static_cast<uint32_t>(new_size64));
779 : }
780 330 : i::wasm::DetachMemoryBuffer(i_isolate, old_buffer, free_memory);
781 : }
782 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
783 330 : return_value.Set(ret);
784 : }
785 :
786 : // WebAssembly.Memory.buffer -> ArrayBuffer
787 5110 : void WebAssemblyMemoryGetBuffer(
788 15262 : const v8::FunctionCallbackInfo<v8::Value>& args) {
789 : v8::Isolate* isolate = args.GetIsolate();
790 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
791 5110 : HandleScope scope(isolate);
792 : i::wasm::ScheduledErrorThrower thrower(i_isolate,
793 5042 : "WebAssembly.Memory.buffer");
794 10220 : EXTRACT_THIS(receiver, WasmMemoryObject);
795 :
796 : i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
797 : DCHECK(buffer_obj->IsJSArrayBuffer());
798 : i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj));
799 5042 : if (buffer->is_shared()) {
800 : // TODO(gdeepti): More needed here for when cached buffer, and current
801 : // buffer are out of sync, handle that here when bounds checks, and Grow
802 : // are handled correctly.
803 : Maybe<bool> result =
804 2982 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::Object::DONT_THROW);
805 2982 : if (!result.FromJust()) {
806 : thrower.TypeError(
807 0 : "Status of setting SetIntegrityLevel of buffer is false.");
808 : }
809 : }
810 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
811 5042 : return_value.Set(Utils::ToLocal(buffer));
812 : }
813 : } // namespace
814 :
815 : // TODO(titzer): we use the API to create the function template because the
816 : // internal guts are too ugly to replicate here.
817 1402993 : static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
818 : FunctionCallback func) {
819 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
820 1402993 : Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
821 1402993 : templ->ReadOnlyPrototype();
822 1402993 : return v8::Utils::OpenHandle(*templ);
823 : }
824 :
825 : namespace internal {
826 :
827 1155406 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
828 : const char* str, FunctionCallback func,
829 : int length = 0) {
830 : Handle<String> name = v8_str(isolate, str);
831 1155406 : Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
832 : Handle<JSFunction> function =
833 2310811 : ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
834 : DCHECK(function->shared()->has_shared_name());
835 : function->shared()->set_length(length);
836 : PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
837 1155405 : JSObject::AddProperty(object, name, function, attributes);
838 1155406 : return function;
839 : }
840 :
841 247587 : void InstallGetter(Isolate* isolate, Handle<JSObject> object,
842 : const char* str, FunctionCallback func) {
843 : Handle<String> name = v8_str(isolate, str);
844 247587 : Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
845 : // TODO(ishell): shouldn't we set "get "+name as getter's name?
846 : Handle<JSFunction> function =
847 495174 : ApiNatives::InstantiateFunction(temp).ToHandleChecked();
848 : DCHECK(function->shared()->has_shared_name());
849 : v8::PropertyAttribute attributes =
850 : static_cast<v8::PropertyAttribute>(v8::DontEnum);
851 : Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
852 : Utils::ToLocal(function),
853 247587 : Local<Function>(), attributes);
854 247587 : }
855 :
856 202620 : void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
857 120091 : Handle<JSGlobalObject> global = isolate->global_object();
858 : Handle<Context> context(global->native_context(), isolate);
859 : // Install the JS API once only.
860 : Object* prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
861 120091 : if (!prev->IsUndefined(isolate)) {
862 : DCHECK(prev->IsJSFunction());
863 37562 : return;
864 : }
865 :
866 : Factory* factory = isolate->factory();
867 :
868 : // Setup WebAssembly
869 : Handle<String> name = v8_str(isolate, "WebAssembly");
870 : Handle<JSFunction> cons = factory->NewFunction(isolate->strict_function_map(),
871 82529 : name, MaybeHandle<Code>());
872 165058 : JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
873 82529 : cons->shared()->set_instance_class_name(*name);
874 82529 : Handle<JSObject> webassembly = factory->NewJSObject(cons, TENURED);
875 : PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
876 :
877 : PropertyAttributes ro_attributes =
878 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
879 : JSObject::AddProperty(webassembly, factory->to_string_tag_symbol(), name,
880 82529 : ro_attributes);
881 82529 : InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
882 82529 : InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
883 82529 : InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
884 :
885 82529 : if (isolate->wasm_compile_streaming_callback() != nullptr) {
886 : InstallFunc(isolate, webassembly, "compileStreaming",
887 0 : WebAssemblyCompileStreaming, 1);
888 : InstallFunc(isolate, webassembly, "instantiateStreaming",
889 0 : WebAssemblyInstantiateStreaming, 1);
890 : }
891 :
892 : // Expose the API on the global object if configured to do so.
893 82529 : if (exposed_on_global_object) {
894 82499 : JSObject::AddProperty(global, name, webassembly, attributes);
895 : }
896 :
897 : // Setup Module
898 : Handle<JSFunction> module_constructor =
899 82529 : InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
900 : context->set_wasm_module_constructor(*module_constructor);
901 82529 : JSFunction::EnsureHasInitialMap(module_constructor);
902 : Handle<JSObject> module_proto(
903 : JSObject::cast(module_constructor->instance_prototype()));
904 : i::Handle<i::Map> module_map = isolate->factory()->NewMap(
905 : i::WASM_MODULE_TYPE, i::JSObject::kHeaderSize +
906 82529 : WasmModuleObject::kFieldCount * i::kPointerSize);
907 82529 : JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
908 : InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
909 82529 : 1);
910 : InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
911 82529 : 1);
912 : InstallFunc(isolate, module_constructor, "customSections",
913 82529 : WebAssemblyModuleCustomSections, 2);
914 : JSObject::AddProperty(module_proto, factory->to_string_tag_symbol(),
915 82529 : v8_str(isolate, "WebAssembly.Module"), ro_attributes);
916 :
917 : // Setup Instance
918 : Handle<JSFunction> instance_constructor =
919 82529 : InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
920 : context->set_wasm_instance_constructor(*instance_constructor);
921 82529 : JSFunction::EnsureHasInitialMap(instance_constructor);
922 : Handle<JSObject> instance_proto(
923 : JSObject::cast(instance_constructor->instance_prototype()));
924 : i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
925 82529 : i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
926 82529 : JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
927 : InstallGetter(isolate, instance_proto, "exports",
928 82529 : WebAssemblyInstanceGetExports);
929 : JSObject::AddProperty(instance_proto, factory->to_string_tag_symbol(),
930 82528 : v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
931 :
932 : // Setup Table
933 : Handle<JSFunction> table_constructor =
934 82529 : InstallFunc(isolate, webassembly, "Table", WebAssemblyTable, 1);
935 : context->set_wasm_table_constructor(*table_constructor);
936 82529 : JSFunction::EnsureHasInitialMap(table_constructor);
937 : Handle<JSObject> table_proto(
938 : JSObject::cast(table_constructor->instance_prototype()));
939 : i::Handle<i::Map> table_map =
940 82529 : isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
941 82529 : JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
942 82529 : InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
943 82529 : InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
944 82529 : InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
945 82529 : InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
946 : JSObject::AddProperty(table_proto, factory->to_string_tag_symbol(),
947 82529 : v8_str(isolate, "WebAssembly.Table"), ro_attributes);
948 :
949 : // Setup Memory
950 : Handle<JSFunction> memory_constructor =
951 82529 : InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory, 1);
952 : context->set_wasm_memory_constructor(*memory_constructor);
953 82529 : JSFunction::EnsureHasInitialMap(memory_constructor);
954 : Handle<JSObject> memory_proto(
955 : JSObject::cast(memory_constructor->instance_prototype()));
956 : i::Handle<i::Map> memory_map =
957 82529 : isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
958 82529 : JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
959 82529 : InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
960 82529 : InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
961 : JSObject::AddProperty(memory_proto, factory->to_string_tag_symbol(),
962 82529 : v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
963 :
964 : // Setup errors
965 : attributes = static_cast<PropertyAttributes>(DONT_ENUM);
966 : Handle<JSFunction> compile_error(
967 165058 : isolate->native_context()->wasm_compile_error_function());
968 : JSObject::AddProperty(webassembly, isolate->factory()->CompileError_string(),
969 82529 : compile_error, attributes);
970 : Handle<JSFunction> link_error(
971 165058 : isolate->native_context()->wasm_link_error_function());
972 : JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(),
973 82529 : link_error, attributes);
974 : Handle<JSFunction> runtime_error(
975 165058 : isolate->native_context()->wasm_runtime_error_function());
976 : JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(),
977 82529 : runtime_error, attributes);
978 : }
979 :
980 : #undef ASSIGN
981 : #undef EXTRACT_THIS
982 :
983 : } // namespace internal
984 : } // namespace v8
|