LCOV - code coverage report
Current view: top level - src/wasm - wasm-js.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 375 409 91.7 %
Date: 2017-10-20 Functions: 28 30 93.3 %

          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

Generated by: LCOV version 1.10