LCOV - code coverage report
Current view: top level - src/wasm - wasm-js.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 742 814 91.2 %
Date: 2019-03-21 Functions: 73 89 82.0 %

          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/wasm/wasm-js.h"
       6             : 
       7             : #include <string>
       8             : 
       9             : #include "src/api-inl.h"
      10             : #include "src/api-natives.h"
      11             : #include "src/assert-scope.h"
      12             : #include "src/ast/ast.h"
      13             : #include "src/base/overflowing-math.h"
      14             : #include "src/execution.h"
      15             : #include "src/handles.h"
      16             : #include "src/heap/factory.h"
      17             : #include "src/isolate.h"
      18             : #include "src/objects-inl.h"
      19             : #include "src/objects/js-promise-inl.h"
      20             : #include "src/objects/templates.h"
      21             : #include "src/parsing/parse-info.h"
      22             : #include "src/task-utils.h"
      23             : #include "src/trap-handler/trap-handler.h"
      24             : #include "src/v8.h"
      25             : #include "src/wasm/streaming-decoder.h"
      26             : #include "src/wasm/wasm-engine.h"
      27             : #include "src/wasm/wasm-limits.h"
      28             : #include "src/wasm/wasm-memory.h"
      29             : #include "src/wasm/wasm-objects-inl.h"
      30             : #include "src/wasm/wasm-serialization.h"
      31             : 
      32             : using v8::internal::wasm::ErrorThrower;
      33             : 
      34             : namespace v8 {
      35             : 
      36          48 : class WasmStreaming::WasmStreamingImpl {
      37             :  public:
      38          24 :   WasmStreamingImpl(
      39             :       Isolate* isolate,
      40             :       std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
      41          24 :       : isolate_(isolate), resolver_(std::move(resolver)) {
      42          24 :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
      43          24 :     auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
      44          72 :     streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
      45             :         i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
      46             :         resolver_);
      47          24 :   }
      48             : 
      49             :   void OnBytesReceived(const uint8_t* bytes, size_t size) {
      50           8 :     streaming_decoder_->OnBytesReceived(i::VectorOf(bytes, size));
      51             :   }
      52           8 :   void Finish() { streaming_decoder_->Finish(); }
      53             : 
      54           8 :   void Abort(MaybeLocal<Value> exception) {
      55           8 :     i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
      56           8 :     streaming_decoder_->Abort();
      57             : 
      58             :     // If no exception value is provided, we do not reject the promise. This can
      59             :     // happen when streaming compilation gets aborted when no script execution
      60             :     // is allowed anymore, e.g. when a browser tab gets refreshed.
      61           8 :     if (exception.IsEmpty()) return;
      62             : 
      63             :     resolver_->OnCompilationFailed(
      64           8 :         Utils::OpenHandle(*exception.ToLocalChecked()));
      65             :   }
      66             : 
      67           0 :   bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
      68           0 :     if (!i::wasm::IsSupportedVersion({bytes, size})) return false;
      69           0 :     return streaming_decoder_->SetCompiledModuleBytes({bytes, size});
      70             :   }
      71             : 
      72           0 :   void SetClient(std::shared_ptr<Client> client) {
      73             :     // There are no other event notifications so just pass client to decoder.
      74             :     // Wrap the client with a callback to trigger the callback in a new
      75             :     // foreground task.
      76           0 :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
      77           0 :     v8::Platform* platform = i::V8::GetCurrentPlatform();
      78             :     std::shared_ptr<TaskRunner> foreground_task_runner =
      79           0 :         platform->GetForegroundTaskRunner(isolate_);
      80           0 :     streaming_decoder_->SetModuleCompiledCallback(
      81           0 :         [client, i_isolate, foreground_task_runner](
      82           0 :             const std::shared_ptr<i::wasm::NativeModule>& native_module) {
      83           0 :           foreground_task_runner->PostTask(
      84           0 :               i::MakeCancelableTask(i_isolate, [client, native_module] {
      85           0 :                 client->OnModuleCompiled(Utils::Convert(native_module));
      86           0 :               }));
      87           0 :         });
      88           0 :   }
      89             : 
      90             :  private:
      91             :   Isolate* const isolate_;
      92             :   std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
      93             :   std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
      94             : };
      95             : 
      96           0 : WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl)
      97           0 :     : impl_(std::move(impl)) {}
      98             : 
      99             : // The destructor is defined here because we have a unique_ptr with forward
     100             : // declaration.
     101             : WasmStreaming::~WasmStreaming() = default;
     102             : 
     103           8 : void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
     104             :   impl_->OnBytesReceived(bytes, size);
     105           8 : }
     106             : 
     107          16 : void WasmStreaming::Finish() { impl_->Finish(); }
     108             : 
     109           8 : void WasmStreaming::Abort(MaybeLocal<Value> exception) {
     110           8 :   impl_->Abort(exception);
     111           8 : }
     112             : 
     113           0 : bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
     114           0 :   return impl_->SetCompiledModuleBytes(bytes, size);
     115             : }
     116             : 
     117           0 : void WasmStreaming::SetClient(std::shared_ptr<Client> client) {
     118           0 :   impl_->SetClient(client);
     119           0 : }
     120             : 
     121             : // static
     122          20 : std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
     123             :                                                      Local<Value> value) {
     124             :   i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate));
     125             :   auto managed =
     126             :       i::Handle<i::Managed<WasmStreaming>>::cast(Utils::OpenHandle(*value));
     127          20 :   return managed->get();
     128             : }
     129             : 
     130             : namespace {
     131             : 
     132             : #define ASSIGN(type, var, expr)                      \
     133             :   Local<type> var;                                   \
     134             :   do {                                               \
     135             :     if (!expr.ToLocal(&var)) {                       \
     136             :       DCHECK(i_isolate->has_scheduled_exception());  \
     137             :       return;                                        \
     138             :     } else {                                         \
     139             :       DCHECK(!i_isolate->has_scheduled_exception()); \
     140             :     }                                                \
     141             :   } while (false)
     142             : 
     143             : // Like an ErrorThrower, but turns all pending exceptions into scheduled
     144             : // exceptions when going out of scope. Use this in API methods.
     145             : // Note that pending exceptions are not necessarily created by the ErrorThrower,
     146             : // but e.g. by the wasm start function. There might also be a scheduled
     147             : // exception, created by another API call (e.g. v8::Object::Get). But there
     148             : // should never be both pending and scheduled exceptions.
     149             : class ScheduledErrorThrower : public ErrorThrower {
     150             :  public:
     151             :   ScheduledErrorThrower(i::Isolate* isolate, const char* context)
     152             :       : ErrorThrower(isolate, context) {}
     153             : 
     154             :   ~ScheduledErrorThrower();
     155             : };
     156             : 
     157   107740740 : ScheduledErrorThrower::~ScheduledErrorThrower() {
     158             :   // There should never be both a pending and a scheduled exception.
     159             :   DCHECK(!isolate()->has_scheduled_exception() ||
     160             :          !isolate()->has_pending_exception());
     161             :   // Don't throw another error if there is already a scheduled error.
     162    53870370 :   if (isolate()->has_scheduled_exception()) {
     163        1808 :     Reset();
     164    53868562 :   } else if (isolate()->has_pending_exception()) {
     165          48 :     Reset();
     166          48 :     isolate()->OptionalRescheduleException(false);
     167    53868514 :   } else if (error()) {
     168       47376 :     isolate()->ScheduleThrow(*Reify());
     169             :   }
     170    53870370 : }
     171             : 
     172             : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
     173     2141838 :   return isolate->factory()->NewStringFromAsciiChecked(str);
     174             : }
     175             : Local<String> v8_str(Isolate* isolate, const char* str) {
     176             :   return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
     177             : }
     178             : 
     179             : #define GET_FIRST_ARGUMENT_AS(Type)                                  \
     180             :   i::MaybeHandle<i::Wasm##Type##Object> GetFirstArgumentAs##Type(    \
     181             :       const v8::FunctionCallbackInfo<v8::Value>& args,               \
     182             :       ErrorThrower* thrower) {                                       \
     183             :     i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);         \
     184             :     if (!arg0->IsWasm##Type##Object()) {                             \
     185             :       thrower->TypeError("Argument 0 must be a WebAssembly." #Type); \
     186             :       return {};                                                     \
     187             :     }                                                                \
     188             :     Local<Object> obj = Local<Object>::Cast(args[0]);                \
     189             :     return i::Handle<i::Wasm##Type##Object>::cast(                   \
     190             :         v8::Utils::OpenHandle(*obj));                                \
     191             :   }
     192             : 
     193      389875 : GET_FIRST_ARGUMENT_AS(Module)
     194         208 : GET_FIRST_ARGUMENT_AS(Memory)
     195         256 : GET_FIRST_ARGUMENT_AS(Table)
     196         232 : GET_FIRST_ARGUMENT_AS(Global)
     197             : 
     198             : #undef GET_FIRST_ARGUMENT_AS
     199             : 
     200      282082 : i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
     201             :     const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower,
     202             :     bool* is_shared) {
     203             :   const uint8_t* start = nullptr;
     204             :   size_t length = 0;
     205             :   v8::Local<v8::Value> source = args[0];
     206      282082 :   if (source->IsArrayBuffer()) {
     207             :     // A raw array buffer was passed.
     208             :     Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
     209      254176 :     ArrayBuffer::Contents contents = buffer->GetContents();
     210             : 
     211             :     start = reinterpret_cast<const uint8_t*>(contents.Data());
     212             :     length = contents.ByteLength();
     213      254176 :     *is_shared = buffer->IsSharedArrayBuffer();
     214       27911 :   } else if (source->IsTypedArray()) {
     215             :     // A TypedArray was passed.
     216             :     Local<TypedArray> array = Local<TypedArray>::Cast(source);
     217       27432 :     Local<ArrayBuffer> buffer = array->Buffer();
     218             : 
     219       27433 :     ArrayBuffer::Contents contents = buffer->GetContents();
     220             : 
     221             :     start =
     222       27435 :         reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
     223       27439 :     length = array->ByteLength();
     224       27442 :     *is_shared = buffer->IsSharedArrayBuffer();
     225             :   } else {
     226         480 :     thrower->TypeError("Argument 0 must be a buffer source");
     227             :   }
     228             :   DCHECK_IMPLIES(length, start != nullptr);
     229      282099 :   if (length == 0) {
     230         780 :     thrower->CompileError("BufferSource argument is empty");
     231             :   }
     232      282099 :   if (length > i::wasm::kV8MaxWasmModuleSize) {
     233             :     thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
     234           0 :                         i::wasm::kV8MaxWasmModuleSize, length);
     235             :   }
     236      282099 :   if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
     237      281295 :   return i::wasm::ModuleWireBytes(start, start + length);
     238             : }
     239             : 
     240      131782 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
     241             :                                                 ErrorThrower* thrower) {
     242      131782 :   if (arg->IsUndefined()) return {};
     243             : 
     244      124754 :   if (!arg->IsObject()) {
     245         240 :     thrower->TypeError("Argument 1 must be an object");
     246         240 :     return {};
     247             :   }
     248             :   Local<Object> obj = Local<Object>::Cast(arg);
     249      124516 :   return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
     250             : }
     251             : 
     252             : namespace {
     253             : // This class resolves the result of WebAssembly.compile. It just places the
     254             : // compilation result in the supplied {promise}.
     255             : class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
     256             :  public:
     257         808 :   AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
     258        1616 :       : promise_(isolate->global_handles()->Create(*promise)) {
     259             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     260         808 :                                              kGlobalPromiseHandle);
     261         808 :   }
     262             : 
     263        1616 :   ~AsyncCompilationResolver() override {
     264         808 :     i::GlobalHandles::Destroy(promise_.location());
     265         784 :   }
     266             : 
     267         332 :   void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
     268         332 :     if (finished_) return;
     269         332 :     finished_ = true;
     270             :     i::MaybeHandle<i::Object> promise_result =
     271         332 :         i::JSPromise::Resolve(promise_, result);
     272         332 :     CHECK_EQ(promise_result.is_null(),
     273             :              promise_->GetIsolate()->has_pending_exception());
     274             :   }
     275             : 
     276         460 :   void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
     277         460 :     if (finished_) return;
     278         460 :     finished_ = true;
     279             :     i::MaybeHandle<i::Object> promise_result =
     280         460 :         i::JSPromise::Reject(promise_, error_reason);
     281         460 :     CHECK_EQ(promise_result.is_null(),
     282             :              promise_->GetIsolate()->has_pending_exception());
     283             :   }
     284             : 
     285             :  private:
     286             :   static constexpr char kGlobalPromiseHandle[] =
     287             :       "AsyncCompilationResolver::promise_";
     288             :   bool finished_ = false;
     289             :   i::Handle<i::JSPromise> promise_;
     290             : };
     291             : 
     292             : constexpr char AsyncCompilationResolver::kGlobalPromiseHandle[];
     293             : 
     294             : // This class resolves the result of WebAssembly.instantiate(module, imports).
     295             : // It just places the instantiation result in the supplied {promise}.
     296             : class InstantiateModuleResultResolver
     297             :     : public i::wasm::InstantiationResultResolver {
     298             :  public:
     299        7319 :   InstantiateModuleResultResolver(i::Isolate* isolate,
     300             :                                   i::Handle<i::JSPromise> promise)
     301       14638 :       : promise_(isolate->global_handles()->Create(*promise)) {
     302             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     303        7319 :                                              kGlobalPromiseHandle);
     304        7319 :   }
     305             : 
     306       14638 :   ~InstantiateModuleResultResolver() override {
     307        7319 :     i::GlobalHandles::Destroy(promise_.location());
     308        7319 :   }
     309             : 
     310         112 :   void OnInstantiationSucceeded(
     311             :       i::Handle<i::WasmInstanceObject> instance) override {
     312             :     i::MaybeHandle<i::Object> promise_result =
     313         112 :         i::JSPromise::Resolve(promise_, instance);
     314         112 :     CHECK_EQ(promise_result.is_null(),
     315             :              promise_->GetIsolate()->has_pending_exception());
     316         112 :   }
     317             : 
     318        5371 :   void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
     319             :     i::MaybeHandle<i::Object> promise_result =
     320        5371 :         i::JSPromise::Reject(promise_, error_reason);
     321        5371 :     CHECK_EQ(promise_result.is_null(),
     322             :              promise_->GetIsolate()->has_pending_exception());
     323        5371 :   }
     324             : 
     325             :  private:
     326             :   static constexpr char kGlobalPromiseHandle[] =
     327             :       "InstantiateModuleResultResolver::promise_";
     328             :   i::Handle<i::JSPromise> promise_;
     329             : };
     330             : 
     331             : constexpr char InstantiateModuleResultResolver::kGlobalPromiseHandle[];
     332             : 
     333             : // This class resolves the result of WebAssembly.instantiate(bytes, imports).
     334             : // For that it creates a new {JSObject} which contains both the provided
     335             : // {WasmModuleObject} and the resulting {WebAssemblyInstanceObject} itself.
     336             : class InstantiateBytesResultResolver
     337             :     : public i::wasm::InstantiationResultResolver {
     338             :  public:
     339        1812 :   InstantiateBytesResultResolver(i::Isolate* isolate,
     340             :                                  i::Handle<i::JSPromise> promise,
     341             :                                  i::Handle<i::WasmModuleObject> module)
     342             :       : isolate_(isolate),
     343             :         promise_(isolate_->global_handles()->Create(*promise)),
     344        7248 :         module_(isolate_->global_handles()->Create(*module)) {
     345             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     346        1812 :                                              kGlobalPromiseHandle);
     347             :     i::GlobalHandles::AnnotateStrongRetainer(module_.location(),
     348        1812 :                                              kGlobalModuleHandle);
     349        1812 :   }
     350             : 
     351        3624 :   ~InstantiateBytesResultResolver() override {
     352        1812 :     i::GlobalHandles::Destroy(promise_.location());
     353        1812 :     i::GlobalHandles::Destroy(module_.location());
     354        1812 :   }
     355             : 
     356        1164 :   void OnInstantiationSucceeded(
     357             :       i::Handle<i::WasmInstanceObject> instance) override {
     358             :     // The result is a JSObject with 2 fields which contain the
     359             :     // WasmInstanceObject and the WasmModuleObject.
     360             :     i::Handle<i::JSObject> result =
     361        1164 :         isolate_->factory()->NewJSObject(isolate_->object_function());
     362             : 
     363             :     i::Handle<i::String> instance_name =
     364        1164 :         isolate_->factory()
     365        2328 :             ->NewStringFromOneByte(i::StaticCharVector("instance"))
     366             :             .ToHandleChecked();
     367             : 
     368             :     i::Handle<i::String> module_name =
     369        1164 :         isolate_->factory()
     370        2328 :             ->NewStringFromOneByte(i::StaticCharVector("module"))
     371             :             .ToHandleChecked();
     372             : 
     373        2328 :     i::JSObject::AddProperty(isolate_, result, instance_name, instance,
     374        1164 :                              i::NONE);
     375        1164 :     i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);
     376             : 
     377             :     i::MaybeHandle<i::Object> promise_result =
     378        1164 :         i::JSPromise::Resolve(promise_, result);
     379        2328 :     CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
     380        1164 :   }
     381             : 
     382         648 :   void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
     383             :     i::MaybeHandle<i::Object> promise_result =
     384         648 :         i::JSPromise::Reject(promise_, error_reason);
     385        1296 :     CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
     386         648 :   }
     387             : 
     388             :  private:
     389             :   static constexpr char kGlobalPromiseHandle[] =
     390             :       "InstantiateBytesResultResolver::promise_";
     391             :   static constexpr char kGlobalModuleHandle[] =
     392             :       "InstantiateBytesResultResolver::module_";
     393             :   i::Isolate* isolate_;
     394             :   i::Handle<i::JSPromise> promise_;
     395             :   i::Handle<i::WasmModuleObject> module_;
     396             : };
     397             : 
     398             : constexpr char InstantiateBytesResultResolver::kGlobalPromiseHandle[];
     399             : constexpr char InstantiateBytesResultResolver::kGlobalModuleHandle[];
     400             : 
     401             : // This class is the {CompilationResultResolver} for
     402             : // WebAssembly.instantiate(bytes, imports). When compilation finishes,
     403             : // {AsyncInstantiate} is started on the compilation result.
     404             : class AsyncInstantiateCompileResultResolver
     405             :     : public i::wasm::CompilationResultResolver {
     406             :  public:
     407        1836 :   AsyncInstantiateCompileResultResolver(
     408             :       i::Isolate* isolate, i::Handle<i::JSPromise> promise,
     409             :       i::MaybeHandle<i::JSReceiver> maybe_imports)
     410             :       : isolate_(isolate),
     411             :         promise_(isolate_->global_handles()->Create(*promise)),
     412             :         maybe_imports_(maybe_imports.is_null()
     413             :                            ? maybe_imports
     414         744 :                            : isolate_->global_handles()->Create(
     415        5508 :                                  *maybe_imports.ToHandleChecked())) {
     416             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     417        1836 :                                              kGlobalPromiseHandle);
     418        1836 :     if (!maybe_imports_.is_null()) {
     419             :       i::GlobalHandles::AnnotateStrongRetainer(
     420         744 :           maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle);
     421             :     }
     422        1836 :   }
     423             : 
     424        3672 :   ~AsyncInstantiateCompileResultResolver() override {
     425        1836 :     i::GlobalHandles::Destroy(promise_.location());
     426        1836 :     if (!maybe_imports_.is_null()) {
     427         744 :       i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
     428             :     }
     429        3672 :   }
     430             : 
     431        1812 :   void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
     432        1812 :     if (finished_) return;
     433        1812 :     finished_ = true;
     434        3624 :     isolate_->wasm_engine()->AsyncInstantiate(
     435             :         isolate_,
     436        3624 :         base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
     437             :                                                           result),
     438        1812 :         result, maybe_imports_);
     439             :   }
     440             : 
     441          24 :   void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
     442          24 :     if (finished_) return;
     443          24 :     finished_ = true;
     444             :     i::MaybeHandle<i::Object> promise_result =
     445          24 :         i::JSPromise::Reject(promise_, error_reason);
     446          48 :     CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
     447             :   }
     448             : 
     449             :  private:
     450             :   static constexpr char kGlobalPromiseHandle[] =
     451             :       "AsyncInstantiateCompileResultResolver::promise_";
     452             :   static constexpr char kGlobalImportsHandle[] =
     453             :       "AsyncInstantiateCompileResultResolver::module_";
     454             :   bool finished_ = false;
     455             :   i::Isolate* isolate_;
     456             :   i::Handle<i::JSPromise> promise_;
     457             :   i::MaybeHandle<i::JSReceiver> maybe_imports_;
     458             : };
     459             : 
     460             : constexpr char AsyncInstantiateCompileResultResolver::kGlobalPromiseHandle[];
     461             : constexpr char AsyncInstantiateCompileResultResolver::kGlobalImportsHandle[];
     462             : 
     463         976 : std::string ToString(const char* name) { return std::string(name); }
     464             : 
     465         312 : std::string ToString(const i::Handle<i::String> name) {
     466        1560 :   return std::string("Property '") + name->ToCString().get() + "'";
     467             : }
     468             : 
     469             : // Web IDL: '[EnforceRange] unsigned long'
     470             : // Previously called ToNonWrappingUint32 in the draft WebAssembly JS spec.
     471             : // https://heycam.github.io/webidl/#EnforceRange
     472             : template <typename T>
     473       24972 : bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context,
     474             :                    ErrorThrower* thrower, uint32_t* res) {
     475             :   double double_number;
     476             : 
     477       49944 :   if (!v->NumberValue(context).To(&double_number)) {
     478         128 :     thrower->TypeError("%s must be convertible to a number",
     479             :                        ToString(argument_name).c_str());
     480          64 :     return false;
     481             :   }
     482       24908 :   if (!std::isfinite(double_number)) {
     483        1152 :     thrower->TypeError("%s must be convertible to a valid number",
     484             :                        ToString(argument_name).c_str());
     485         576 :     return false;
     486             :   }
     487       24332 :   if (double_number < 0) {
     488         736 :     thrower->TypeError("%s must be non-negative",
     489             :                        ToString(argument_name).c_str());
     490         368 :     return false;
     491             :   }
     492       23964 :   if (double_number > std::numeric_limits<uint32_t>::max()) {
     493         560 :     thrower->TypeError("%s must be in the unsigned long range",
     494             :                        ToString(argument_name).c_str());
     495         280 :     return false;
     496             :   }
     497             : 
     498       23684 :   *res = static_cast<uint32_t>(double_number);
     499       23684 :   return true;
     500             : }
     501             : }  // namespace
     502             : 
     503             : // WebAssembly.compile(bytes) -> Promise
     504         784 : void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
     505             :   v8::Isolate* isolate = args.GetIsolate();
     506             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     507             : 
     508        1324 :   HandleScope scope(isolate);
     509         540 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
     510             : 
     511        1568 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     512          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     513             :   }
     514             : 
     515         784 :   Local<Context> context = isolate->GetCurrentContext();
     516        1812 :   ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
     517         784 :   Local<Promise> promise = promise_resolver->GetPromise();
     518             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     519             :   return_value.Set(promise);
     520             : 
     521             :   std::shared_ptr<i::wasm::CompilationResultResolver> resolver(
     522        1568 :       new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
     523             : 
     524         784 :   bool is_shared = false;
     525         784 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     526         784 :   if (thrower.error()) {
     527         244 :     resolver->OnCompilationFailed(thrower.Reify());
     528             :     return;
     529             :   }
     530             :   // Asynchronous compilation handles copying wire bytes if necessary.
     531         540 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     532        1080 :   i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
     533         540 :                                          std::move(resolver), bytes, is_shared);
     534             : }
     535             : 
     536             : // WebAssembly.compileStreaming(Promise<Response>) -> Promise
     537          24 : void WebAssemblyCompileStreaming(
     538             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     539             :   v8::Isolate* isolate = args.GetIsolate();
     540          24 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     541          48 :   HandleScope scope(isolate);
     542          48 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
     543          24 :   Local<Context> context = isolate->GetCurrentContext();
     544             : 
     545             :   // Create and assign the return value of this function.
     546          48 :   ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
     547          24 :   Local<Promise> promise = result_resolver->GetPromise();
     548             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     549             :   return_value.Set(promise);
     550             : 
     551             :   // Prepare the CompilationResultResolver for the compilation.
     552             :   auto resolver = std::make_shared<AsyncCompilationResolver>(
     553          48 :       i_isolate, Utils::OpenHandle(*promise));
     554             : 
     555          48 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     556           0 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     557           0 :     resolver->OnCompilationFailed(thrower.Reify());
     558           0 :     return;
     559             :   }
     560             : 
     561             :   // Allocate the streaming decoder in a Managed so we can pass it to the
     562             :   // embedder.
     563             :   i::Handle<i::Managed<WasmStreaming>> data =
     564             :       i::Managed<WasmStreaming>::Allocate(
     565             :           i_isolate, 0,
     566          48 :           base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
     567          24 :                                                               resolver));
     568             : 
     569             :   DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
     570          48 :   ASSIGN(
     571             :       v8::Function, compile_callback,
     572             :       v8::Function::New(context, i_isolate->wasm_streaming_callback(),
     573             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     574             : 
     575             :   // The parameter may be of type {Response} or of type {Promise<Response>}.
     576             :   // Treat either case of parameter as Promise.resolve(parameter)
     577             :   // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
     578             : 
     579             :   // Ending with:
     580             :   //    return Promise.resolve(parameter).then(compile_callback);
     581          48 :   ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
     582          48 :   if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
     583             : 
     584             :   // We do not have any use of the result here. The {compile_callback} will
     585             :   // start streaming compilation, which will eventually resolve the promise we
     586             :   // set as result value.
     587          48 :   USE(input_resolver->GetPromise()->Then(context, compile_callback));
     588             : }
     589             : 
     590             : // WebAssembly.validate(bytes) -> bool
     591      128200 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
     592             :   v8::Isolate* isolate = args.GetIsolate();
     593             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     594      256208 :   HandleScope scope(isolate);
     595      128008 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
     596             : 
     597      128200 :   bool is_shared = false;
     598      128200 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     599             : 
     600             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     601             : 
     602      128200 :   if (thrower.error()) {
     603         192 :     if (thrower.wasm_error()) thrower.Reset();  // Clear error.
     604             :     return_value.Set(v8::False(isolate));
     605         192 :     return;
     606             :   }
     607             : 
     608      128008 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     609             :   bool validated = false;
     610      128008 :   if (is_shared) {
     611             :     // Make a copy of the wire bytes to avoid concurrent modification.
     612           0 :     std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
     613             :     memcpy(copy.get(), bytes.start(), bytes.length());
     614             :     i::wasm::ModuleWireBytes bytes_copy(copy.get(),
     615           0 :                                         copy.get() + bytes.length());
     616             :     validated = i_isolate->wasm_engine()->SyncValidate(
     617           0 :         i_isolate, enabled_features, bytes_copy);
     618             :   } else {
     619             :     // The wire bytes are not shared, OK to use them directly.
     620             :     validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
     621      128008 :                                                        enabled_features, bytes);
     622             :   }
     623             : 
     624             :   return_value.Set(Boolean::New(isolate, validated));
     625             : }
     626             : 
     627             : // new WebAssembly.Module(bytes) -> WebAssembly.Module
     628      151230 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
     629             :   v8::Isolate* isolate = args.GetIsolate();
     630             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     631      168134 :   if (i_isolate->wasm_module_callback()(args)) return;
     632             : 
     633      285557 :   HandleScope scope(isolate);
     634      134332 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
     635             : 
     636      151222 :   if (!args.IsConstructCall()) {
     637          32 :     thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
     638          32 :     return;
     639             :   }
     640      302379 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     641          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     642          24 :     return;
     643             :   }
     644             : 
     645      151160 :   bool is_shared = false;
     646      151160 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     647             : 
     648      151175 :   if (thrower.error()) {
     649             :     return;
     650             :   }
     651      150909 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     652             :   i::MaybeHandle<i::Object> module_obj;
     653      150903 :   if (is_shared) {
     654             :     // Make a copy of the wire bytes to avoid concurrent modification.
     655           0 :     std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
     656             :     memcpy(copy.get(), bytes.start(), bytes.length());
     657             :     i::wasm::ModuleWireBytes bytes_copy(copy.get(),
     658           0 :                                         copy.get() + bytes.length());
     659             :     module_obj = i_isolate->wasm_engine()->SyncCompile(
     660           0 :         i_isolate, enabled_features, &thrower, bytes_copy);
     661             :   } else {
     662             :     // The wire bytes are not shared, OK to use them directly.
     663             :     module_obj = i_isolate->wasm_engine()->SyncCompile(
     664      150903 :         i_isolate, enabled_features, &thrower, bytes);
     665             :   }
     666             : 
     667      150905 :   if (module_obj.is_null()) return;
     668             : 
     669             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     670             :   return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
     671             : }
     672             : 
     673             : // WebAssembly.Module.imports(module) -> Array<Import>
     674         248 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
     675         392 :   HandleScope scope(args.GetIsolate());
     676             :   v8::Isolate* isolate = args.GetIsolate();
     677             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     678         144 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
     679             : 
     680         248 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     681         352 :   if (thrower.error()) return;
     682         144 :   auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
     683             :   args.GetReturnValue().Set(Utils::ToLocal(imports));
     684             : }
     685             : 
     686             : // WebAssembly.Module.exports(module) -> Array<Export>
     687         240 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
     688         376 :   HandleScope scope(args.GetIsolate());
     689             :   v8::Isolate* isolate = args.GetIsolate();
     690             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     691         136 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
     692             : 
     693         240 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     694         344 :   if (thrower.error()) return;
     695         136 :   auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
     696             :   args.GetReturnValue().Set(Utils::ToLocal(exports));
     697             : }
     698             : 
     699             : // WebAssembly.Module.customSections(module, name) -> Array<Section>
     700         376 : void WebAssemblyModuleCustomSections(
     701             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     702         624 :   HandleScope scope(args.GetIsolate());
     703             :   v8::Isolate* isolate = args.GetIsolate();
     704             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     705             :   ScheduledErrorThrower thrower(i_isolate,
     706         248 :                                 "WebAssembly.Module.customSections()");
     707             : 
     708         376 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     709         504 :   if (thrower.error()) return;
     710             : 
     711         264 :   if (args[1]->IsUndefined()) {
     712           8 :     thrower.TypeError("Argument 1 is required");
     713           8 :     return;
     714             :   }
     715             : 
     716             :   i::MaybeHandle<i::Object> maybe_name =
     717         256 :       i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
     718             :   i::Handle<i::Object> name;
     719         256 :   if (!maybe_name.ToHandle(&name)) return;
     720             :   auto custom_sections =
     721             :       i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
     722         248 :                                  i::Handle<i::String>::cast(name), &thrower);
     723         248 :   if (thrower.error()) return;
     724             :   args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
     725             : }
     726             : 
     727      129106 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
     728             :                                              Local<Value> module,
     729             :                                              Local<Value> ffi) {
     730             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     731             : 
     732             :   i::MaybeHandle<i::Object> instance_object;
     733             :   {
     734      129028 :     ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
     735             : 
     736             :     // TODO(ahaas): These checks on the module should not be necessary here They
     737             :     // are just a workaround for https://crbug.com/837417.
     738             :     i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
     739      129106 :     if (!module_obj->IsWasmModuleObject()) {
     740           0 :       thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
     741           0 :       return {};
     742             :     }
     743             : 
     744             :     i::MaybeHandle<i::JSReceiver> maybe_imports =
     745      129106 :         GetValueAsImports(ffi, &thrower);
     746      129108 :     if (thrower.error()) return {};
     747             : 
     748             :     instance_object = i_isolate->wasm_engine()->SyncInstantiate(
     749             :         i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
     750      129028 :         maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
     751             :   }
     752             : 
     753             :   DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
     754      129028 :   if (instance_object.is_null()) return {};
     755      127380 :   return Utils::ToLocal(instance_object.ToHandleChecked());
     756             : }
     757             : 
     758             : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
     759      129280 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
     760             :   Isolate* isolate = args.GetIsolate();
     761             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     762             :   i_isolate->CountUsage(
     763      129280 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     764             : 
     765      258390 :   HandleScope scope(args.GetIsolate());
     766      129453 :   if (i_isolate->wasm_instance_callback()(args)) return;
     767             : 
     768      129108 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
     769      129275 :   if (!args.IsConstructCall()) {
     770          24 :     thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
     771          24 :     return;
     772             :   }
     773             : 
     774      129251 :   GetFirstArgumentAsModule(args, &thrower);
     775      129249 :   if (thrower.error()) return;
     776             : 
     777             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     778             :   // We'll check for that in WebAssemblyInstantiateImpl.
     779      129108 :   Local<Value> data = args[1];
     780             : 
     781             :   Local<Value> instance;
     782      258216 :   if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
     783             :     args.GetReturnValue().Set(instance);
     784             :   }
     785             : }
     786             : 
     787           0 : void WebAssemblyInstantiateStreaming(
     788             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     789           0 :   v8::Isolate* isolate = args.GetIsolate();
     790             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     791             :   i_isolate->CountUsage(
     792           0 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     793             : 
     794           0 :   HandleScope scope(isolate);
     795           0 :   Local<Context> context = isolate->GetCurrentContext();
     796             :   ScheduledErrorThrower thrower(i_isolate,
     797           0 :                                 "WebAssembly.instantiateStreaming()");
     798             : 
     799             :   // Create and assign the return value of this function.
     800           0 :   ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
     801           0 :   Local<Promise> promise = result_resolver->GetPromise();
     802             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     803             :   return_value.Set(promise);
     804             : 
     805             :   // Create an InstantiateResultResolver in case there is an issue with the
     806             :   // passed parameters.
     807             :   std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
     808             :       new InstantiateModuleResultResolver(i_isolate,
     809           0 :                                           Utils::OpenHandle(*promise)));
     810             : 
     811           0 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     812           0 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     813           0 :     resolver->OnInstantiationFailed(thrower.Reify());
     814           0 :     return;
     815             :   }
     816             : 
     817             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     818           0 :   Local<Value> ffi = args[1];
     819             :   i::MaybeHandle<i::JSReceiver> maybe_imports =
     820           0 :       GetValueAsImports(ffi, &thrower);
     821             : 
     822           0 :   if (thrower.error()) {
     823           0 :     resolver->OnInstantiationFailed(thrower.Reify());
     824           0 :     return;
     825             :   }
     826             : 
     827             :   // We start compilation now, we have no use for the
     828             :   // {InstantiationResultResolver}.
     829             :   resolver.reset();
     830             : 
     831             :   std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
     832             :       new AsyncInstantiateCompileResultResolver(
     833           0 :           i_isolate, Utils::OpenHandle(*promise), maybe_imports));
     834             : 
     835             :   // Allocate the streaming decoder in a Managed so we can pass it to the
     836             :   // embedder.
     837             :   i::Handle<i::Managed<WasmStreaming>> data =
     838             :       i::Managed<WasmStreaming>::Allocate(
     839             :           i_isolate, 0,
     840           0 :           base::make_unique<WasmStreaming::WasmStreamingImpl>(
     841           0 :               isolate, compilation_resolver));
     842             : 
     843             :   DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
     844           0 :   ASSIGN(
     845             :       v8::Function, compile_callback,
     846             :       v8::Function::New(context, i_isolate->wasm_streaming_callback(),
     847             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     848             : 
     849             :   // The parameter may be of type {Response} or of type {Promise<Response>}.
     850             :   // Treat either case of parameter as Promise.resolve(parameter)
     851             :   // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
     852             : 
     853             :   // Ending with:
     854             :   //    return Promise.resolve(parameter).then(compile_callback);
     855           0 :   ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
     856           0 :   if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
     857             : 
     858             :   // We do not have any use of the result here. The {compile_callback} will
     859             :   // start streaming compilation, which will eventually resolve the promise we
     860             :   // set as result value.
     861           0 :   USE(input_resolver->GetPromise()->Then(context, compile_callback));
     862             : }
     863             : 
     864             : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
     865             : // WebAssembly.instantiate(bytes, imports) ->
     866             : //     {module: WebAssembly.Module, instance: WebAssembly.Instance}
     867        7319 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
     868             :   v8::Isolate* isolate = args.GetIsolate();
     869             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     870             :   i_isolate->CountUsage(
     871        7319 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     872             : 
     873        1812 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
     874             : 
     875        9131 :   HandleScope scope(isolate);
     876             : 
     877        7319 :   Local<Context> context = isolate->GetCurrentContext();
     878             : 
     879       20145 :   ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
     880        7319 :   Local<Promise> promise = promise_resolver->GetPromise();
     881             :   args.GetReturnValue().Set(promise);
     882             : 
     883             :   std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
     884             :       new InstantiateModuleResultResolver(i_isolate,
     885        7319 :                                           Utils::OpenHandle(*promise)));
     886             : 
     887             :   Local<Value> first_arg_value = args[0];
     888             :   i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
     889        7319 :   if (!first_arg->IsJSObject()) {
     890             :     thrower.TypeError(
     891        4643 :         "Argument 0 must be a buffer source or a WebAssembly.Module object");
     892        4643 :     resolver->OnInstantiationFailed(thrower.Reify());
     893        4643 :     return;
     894             :   }
     895             : 
     896             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     897        2676 :   Local<Value> ffi = args[1];
     898             :   i::MaybeHandle<i::JSReceiver> maybe_imports =
     899        2676 :       GetValueAsImports(ffi, &thrower);
     900             : 
     901        2676 :   if (thrower.error()) {
     902         160 :     resolver->OnInstantiationFailed(thrower.Reify());
     903         160 :     return;
     904             :   }
     905             : 
     906        2516 :   if (first_arg->IsWasmModuleObject()) {
     907             :     i::Handle<i::WasmModuleObject> module_obj =
     908         576 :         i::Handle<i::WasmModuleObject>::cast(first_arg);
     909             : 
     910         576 :     i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
     911         576 :                                                module_obj, maybe_imports);
     912             :     return;
     913             :   }
     914             : 
     915        1940 :   bool is_shared = false;
     916        1940 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     917        1940 :   if (thrower.error()) {
     918         104 :     resolver->OnInstantiationFailed(thrower.Reify());
     919         104 :     return;
     920             :   }
     921             : 
     922             :   // We start compilation now, we have no use for the
     923             :   // {InstantiationResultResolver}.
     924             :   resolver.reset();
     925             : 
     926             :   std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
     927             :       new AsyncInstantiateCompileResultResolver(
     928        3672 :           i_isolate, Utils::OpenHandle(*promise), maybe_imports));
     929             : 
     930             :   // The first parameter is a buffer source, we have to check if we are allowed
     931             :   // to compile it.
     932        3672 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     933          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     934          24 :     compilation_resolver->OnCompilationFailed(thrower.Reify());
     935             :     return;
     936             :   }
     937             : 
     938             :   // Asynchronous compilation handles copying wire bytes if necessary.
     939        1812 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     940        3624 :   i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
     941             :                                          std::move(compilation_resolver), bytes,
     942        1812 :                                          is_shared);
     943             : }
     944             : 
     945        8808 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
     946             :                         Local<Context> context, v8::Local<v8::Value> value,
     947             :                         i::Handle<i::String> property_name, int64_t* result,
     948             :                         int64_t lower_bound, uint64_t upper_bound) {
     949             :   uint32_t number;
     950        8808 :   if (!EnforceUint32(property_name, value, context, thrower, &number)) {
     951             :     return false;
     952             :   }
     953        8496 :   if (number < lower_bound) {
     954             :     thrower->RangeError("Property '%s': value %" PRIu32
     955             :                         " is below the lower bound %" PRIx64,
     956         144 :                         property_name->ToCString().get(), number, lower_bound);
     957             :     return false;
     958             :   }
     959        8448 :   if (number > upper_bound) {
     960             :     thrower->RangeError("Property '%s': value %" PRIu32
     961             :                         " is above the upper bound %" PRIu64,
     962         192 :                         property_name->ToCString().get(), number, upper_bound);
     963             :     return false;
     964             :   }
     965             : 
     966        8384 :   *result = static_cast<int64_t>(number);
     967             :   return true;
     968             : }
     969             : 
     970       12830 : bool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
     971             :                                 Local<Context> context,
     972             :                                 Local<v8::Object> object,
     973             :                                 Local<String> property, bool* has_property,
     974             :                                 int64_t* result, int64_t lower_bound,
     975             :                                 uint64_t upper_bound) {
     976             :   v8::Local<v8::Value> value;
     977       25660 :   if (!object->Get(context, property).ToLocal(&value)) {
     978             :     return false;
     979             :   }
     980             : 
     981             :   // Web IDL: dictionary presence
     982             :   // https://heycam.github.io/webidl/#dfn-present
     983       12830 :   if (value->IsUndefined()) {
     984        4022 :     if (has_property != nullptr) *has_property = false;
     985             :     return true;
     986             :   }
     987             : 
     988        8808 :   if (has_property != nullptr) *has_property = true;
     989        8808 :   i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property);
     990             : 
     991             :   return GetIntegerProperty(isolate, thrower, context, value, property_name,
     992        8808 :                             result, lower_bound, upper_bound);
     993             : }
     994             : 
     995             : // Fetch 'initial' or 'minimum' property from object. If both are provided,
     996             : // 'initial' is used.
     997             : // TODO(aseemgarg): change behavior when the following bug is resolved:
     998             : // https://github.com/WebAssembly/js-types/issues/6
     999        6519 : bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
    1000             :                                  Local<Context> context,
    1001             :                                  Local<v8::Object> object, int64_t* result,
    1002             :                                  int64_t lower_bound, uint64_t upper_bound) {
    1003        6519 :   bool has_initial = false;
    1004        6519 :   if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
    1005             :                                   v8_str(isolate, "initial"), &has_initial,
    1006             :                                   result, lower_bound, upper_bound)) {
    1007             :     return false;
    1008             :   }
    1009        6311 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1010        6311 :   if (!has_initial && enabled_features.type_reflection) {
    1011          32 :     if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
    1012             :                                     v8_str(isolate, "minimum"), &has_initial,
    1013             :                                     result, lower_bound, upper_bound)) {
    1014             :       return false;
    1015             :     }
    1016             :   }
    1017        6311 :   if (!has_initial) {
    1018             :     // TODO(aseemgarg): update error message when the spec issue is resolved.
    1019          32 :     thrower->TypeError("Property 'initial' is required");
    1020          32 :     return false;
    1021             :   }
    1022             :   return true;
    1023             : }
    1024             : 
    1025             : // new WebAssembly.Table(args) -> WebAssembly.Table
    1026        2152 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1027             :   v8::Isolate* isolate = args.GetIsolate();
    1028             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1029        3848 :   HandleScope scope(isolate);
    1030        1696 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
    1031        2152 :   if (!args.IsConstructCall()) {
    1032          24 :     thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
    1033          24 :     return;
    1034             :   }
    1035        2128 :   if (!args[0]->IsObject()) {
    1036         120 :     thrower.TypeError("Argument 0 must be a table descriptor");
    1037         120 :     return;
    1038             :   }
    1039        2008 :   Local<Context> context = isolate->GetCurrentContext();
    1040             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1041             :   i::wasm::ValueType type;
    1042             :   // The descriptor's 'element'.
    1043             :   {
    1044             :     v8::MaybeLocal<v8::Value> maybe =
    1045        2008 :         descriptor->Get(context, v8_str(isolate, "element"));
    1046             :     v8::Local<v8::Value> value;
    1047        2096 :     if (!maybe.ToLocal(&value)) return;
    1048             :     v8::Local<v8::String> string;
    1049        4016 :     if (!value->ToString(context).ToLocal(&string)) return;
    1050        2008 :     auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1051        2008 :     if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
    1052             :       type = i::wasm::kWasmAnyFunc;
    1053         136 :     } else if (enabled_features.anyref &&
    1054          24 :                string->StringEquals(v8_str(isolate, "anyref"))) {
    1055             :       type = i::wasm::kWasmAnyRef;
    1056             :     } else {
    1057          88 :       thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
    1058          88 :       return;
    1059             :     }
    1060             :   }
    1061             : 
    1062        1920 :   int64_t initial = 0;
    1063        1920 :   if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
    1064             :                                    &initial, 0,
    1065        1920 :                                    i::wasm::max_table_init_entries())) {
    1066             :     return;
    1067             :   }
    1068             :   // The descriptor's 'maximum'.
    1069        1816 :   int64_t maximum = -1;
    1070        1816 :   bool has_maximum = true;
    1071        3632 :   if (!GetOptionalIntegerProperty(
    1072             :           isolate, &thrower, context, descriptor, v8_str(isolate, "maximum"),
    1073        1816 :           &has_maximum, &maximum, initial, i::wasm::max_table_init_entries())) {
    1074             :     return;
    1075             :   }
    1076             : 
    1077             :   i::Handle<i::FixedArray> fixed_array;
    1078             :   i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
    1079             :       i_isolate, type, static_cast<uint32_t>(initial), has_maximum,
    1080        1696 :       static_cast<uint32_t>(maximum), &fixed_array);
    1081             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1082             :   return_value.Set(Utils::ToLocal(table_obj));
    1083             : }
    1084             : 
    1085        4743 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1086             :   v8::Isolate* isolate = args.GetIsolate();
    1087             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1088        9094 :   HandleScope scope(isolate);
    1089        4351 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
    1090        4743 :   if (!args.IsConstructCall()) {
    1091          24 :     thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
    1092          24 :     return;
    1093             :   }
    1094        4719 :   if (!args[0]->IsObject()) {
    1095         120 :     thrower.TypeError("Argument 0 must be a memory descriptor");
    1096         120 :     return;
    1097             :   }
    1098        4599 :   Local<Context> context = isolate->GetCurrentContext();
    1099             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1100             : 
    1101        4599 :   int64_t initial = 0;
    1102        4599 :   if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
    1103        4599 :                                    &initial, 0, i::wasm::max_mem_pages())) {
    1104             :     return;
    1105             :   }
    1106             :   // The descriptor's 'maximum'.
    1107        4463 :   int64_t maximum = -1;
    1108        8926 :   if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
    1109             :                                   v8_str(isolate, "maximum"), nullptr, &maximum,
    1110             :                                   initial, i::wasm::kSpecMaxWasmMemoryPages)) {
    1111             :     return;
    1112             :   }
    1113             : 
    1114             :   bool is_shared_memory = false;
    1115        4367 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1116        4367 :   if (enabled_features.threads) {
    1117             :     // Shared property of descriptor
    1118             :     Local<String> shared_key = v8_str(isolate, "shared");
    1119             :     v8::MaybeLocal<v8::Value> maybe_value =
    1120         297 :         descriptor->Get(context, shared_key);
    1121             :     v8::Local<v8::Value> value;
    1122         297 :     if (maybe_value.ToLocal(&value)) {
    1123         297 :       is_shared_memory = value->BooleanValue(isolate);
    1124             :     }
    1125             :     // Throw TypeError if shared is true, and the descriptor has no "maximum"
    1126         297 :     if (is_shared_memory && maximum == -1) {
    1127             :       thrower.TypeError(
    1128           8 :           "If shared is true, maximum property should be defined.");
    1129             :       return;
    1130             :     }
    1131             :   }
    1132             : 
    1133             :   i::Handle<i::JSObject> memory_obj;
    1134        8718 :   if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
    1135             :                                 static_cast<uint32_t>(maximum),
    1136        4359 :                                 is_shared_memory)
    1137             :            .ToHandle(&memory_obj)) {
    1138           8 :     thrower.RangeError("could not allocate memory");
    1139           8 :     return;
    1140             :   }
    1141        4351 :   if (is_shared_memory) {
    1142             :     i::Handle<i::JSArrayBuffer> buffer(
    1143             :         i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(),
    1144             :         i_isolate);
    1145             :     Maybe<bool> result =
    1146         249 :         buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    1147         249 :     if (!result.FromJust()) {
    1148             :       thrower.TypeError(
    1149           0 :           "Status of setting SetIntegrityLevel of buffer is false.");
    1150             :       return;
    1151             :     }
    1152             :   }
    1153             :   args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
    1154             : }
    1155             : 
    1156        7392 : void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1157             :   v8::Isolate* isolate = args.GetIsolate();
    1158             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1159       14528 :   HandleScope scope(isolate);
    1160        7136 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
    1161        7392 :   if (!args.IsConstructCall()) {
    1162           8 :     thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
    1163           8 :     return;
    1164             :   }
    1165        7384 :   if (!args[0]->IsObject()) {
    1166         104 :     thrower.TypeError("Argument 0 must be a global descriptor");
    1167         104 :     return;
    1168             :   }
    1169        7280 :   Local<Context> context = isolate->GetCurrentContext();
    1170             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1171             : 
    1172             :   // The descriptor's 'mutable'.
    1173             :   bool is_mutable = false;
    1174             :   {
    1175             :     Local<String> mutable_key = v8_str(isolate, "mutable");
    1176        7280 :     v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
    1177             :     v8::Local<v8::Value> value;
    1178        7280 :     if (maybe.ToLocal(&value)) {
    1179        7280 :       is_mutable = value->BooleanValue(isolate);
    1180             :     }
    1181             :   }
    1182             : 
    1183             :   // The descriptor's type, called 'value'. It is called 'value' because this
    1184             :   // descriptor is planned to be re-used as the global's type for reflection,
    1185             :   // so calling it 'type' is redundant.
    1186             :   i::wasm::ValueType type;
    1187             :   {
    1188             :     v8::MaybeLocal<v8::Value> maybe =
    1189        7280 :         descriptor->Get(context, v8_str(isolate, "value"));
    1190             :     v8::Local<v8::Value> value;
    1191        7400 :     if (!maybe.ToLocal(&value)) return;
    1192             :     v8::Local<v8::String> string;
    1193       14560 :     if (!value->ToString(context).ToLocal(&string)) return;
    1194             : 
    1195        7280 :     auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1196        7280 :     if (string->StringEquals(v8_str(isolate, "i32"))) {
    1197             :       type = i::wasm::kWasmI32;
    1198        4696 :     } else if (string->StringEquals(v8_str(isolate, "f32"))) {
    1199             :       type = i::wasm::kWasmF32;
    1200        1760 :     } else if (string->StringEquals(v8_str(isolate, "i64"))) {
    1201             :       type = i::wasm::kWasmI64;
    1202        1664 :     } else if (string->StringEquals(v8_str(isolate, "f64"))) {
    1203             :       type = i::wasm::kWasmF64;
    1204         488 :     } else if (enabled_features.anyref &&
    1205         184 :                string->StringEquals(v8_str(isolate, "anyref"))) {
    1206             :       type = i::wasm::kWasmAnyRef;
    1207         232 :     } else if (enabled_features.anyref &&
    1208          56 :                string->StringEquals(v8_str(isolate, "anyfunc"))) {
    1209             :       type = i::wasm::kWasmAnyFunc;
    1210             :     } else {
    1211             :       thrower.TypeError(
    1212             :           "Descriptor property 'value' must be 'i32', 'i64', 'f32', or "
    1213         120 :           "'f64'");
    1214         120 :       return;
    1215             :     }
    1216             :   }
    1217             : 
    1218             :   const uint32_t offset = 0;
    1219             :   i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
    1220             :       i::WasmGlobalObject::New(i_isolate, i::MaybeHandle<i::JSArrayBuffer>(),
    1221             :                                i::MaybeHandle<i::FixedArray>(), type, offset,
    1222        7160 :                                is_mutable);
    1223             : 
    1224             :   i::Handle<i::WasmGlobalObject> global_obj;
    1225        7160 :   if (!maybe_global_obj.ToHandle(&global_obj)) {
    1226           0 :     thrower.RangeError("could not allocate memory");
    1227           0 :     return;
    1228             :   }
    1229             : 
    1230             :   // Convert value to a WebAssembly value, the default value is 0.
    1231             :   Local<v8::Value> value = Local<Value>::Cast(args[1]);
    1232        7160 :   switch (type) {
    1233             :     case i::wasm::kWasmI32: {
    1234             :       int32_t i32_value = 0;
    1235        2584 :       if (!value->IsUndefined()) {
    1236             :         v8::Local<v8::Int32> int32_value;
    1237        4832 :         if (!value->ToInt32(context).ToLocal(&int32_value)) return;
    1238        4832 :         if (!int32_value->Int32Value(context).To(&i32_value)) return;
    1239             :       }
    1240        2584 :       global_obj->SetI32(i32_value);
    1241             :       break;
    1242             :     }
    1243             :     case i::wasm::kWasmI64: {
    1244             :       int64_t i64_value = 0;
    1245          96 :       if (!value->IsUndefined()) {
    1246          48 :         auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1247          48 :         if (!enabled_features.bigint) {
    1248          16 :           thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
    1249          16 :           return;
    1250             :         }
    1251             : 
    1252             :         v8::Local<v8::BigInt> bigint_value;
    1253          64 :         if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
    1254          24 :         i64_value = bigint_value->Int64Value();
    1255             :       }
    1256          72 :       global_obj->SetI64(i64_value);
    1257          72 :       break;
    1258             :     }
    1259             :     case i::wasm::kWasmF32: {
    1260             :       float f32_value = 0;
    1261        2936 :       if (!value->IsUndefined()) {
    1262             :         double f64_value = 0;
    1263             :         v8::Local<v8::Number> number_value;
    1264        5600 :         if (!value->ToNumber(context).ToLocal(&number_value)) return;
    1265        5600 :         if (!number_value->NumberValue(context).To(&f64_value)) return;
    1266        2800 :         f32_value = static_cast<float>(f64_value);
    1267             :       }
    1268        2936 :       global_obj->SetF32(f32_value);
    1269        2936 :       break;
    1270             :     }
    1271             :     case i::wasm::kWasmF64: {
    1272             :       double f64_value = 0;
    1273        1360 :       if (!value->IsUndefined()) {
    1274             :         v8::Local<v8::Number> number_value;
    1275        2448 :         if (!value->ToNumber(context).ToLocal(&number_value)) return;
    1276        2448 :         if (!number_value->NumberValue(context).To(&f64_value)) return;
    1277             :       }
    1278        1360 :       global_obj->SetF64(f64_value);
    1279             :       break;
    1280             :     }
    1281             :     case i::wasm::kWasmAnyRef: {
    1282         128 :       if (args.Length() < 2) {
    1283             :         // When no inital value is provided, we have to use the WebAssembly
    1284             :         // default value 'null', and not the JS default value 'undefined'.
    1285          32 :         global_obj->SetAnyRef(i_isolate->factory()->null_value());
    1286          32 :         break;
    1287             :       }
    1288          96 :       global_obj->SetAnyRef(Utils::OpenHandle(*value));
    1289          96 :       break;
    1290             :     }
    1291             :     case i::wasm::kWasmAnyFunc: {
    1292          56 :       if (args.Length() < 2) {
    1293             :         // When no inital value is provided, we have to use the WebAssembly
    1294             :         // default value 'null', and not the JS default value 'undefined'.
    1295          16 :         global_obj->SetAnyFunc(i_isolate, i_isolate->factory()->null_value());
    1296          16 :         break;
    1297             :       }
    1298             : 
    1299          40 :       if (!global_obj->SetAnyFunc(i_isolate, Utils::OpenHandle(*value))) {
    1300             :         thrower.TypeError(
    1301             :             "The value of anyfunc globals must be null or an "
    1302           8 :             "exported function");
    1303             :       }
    1304             :       break;
    1305             :     }
    1306             :     default:
    1307           0 :       UNREACHABLE();
    1308             :   }
    1309             : 
    1310             :   i::Handle<i::JSObject> global_js_object(global_obj);
    1311             :   args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
    1312             : }
    1313             : 
    1314             : // WebAssembly.Exception
    1315           8 : void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1316             :   v8::Isolate* isolate = args.GetIsolate();
    1317             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1318          16 :   HandleScope scope(isolate);
    1319           8 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
    1320           8 :   thrower.TypeError("WebAssembly.Exception cannot be called");
    1321           8 : }
    1322             : 
    1323             : constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
    1324             : constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
    1325             : constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
    1326             : constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
    1327             : 
    1328             : #define EXTRACT_THIS(var, WasmType)                                  \
    1329             :   i::Handle<i::WasmType> var;                                        \
    1330             :   {                                                                  \
    1331             :     i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
    1332             :     if (!this_arg->Is##WasmType()) {                                 \
    1333             :       thrower.TypeError("Receiver is not a %s", kName_##WasmType);   \
    1334             :       return;                                                        \
    1335             :     }                                                                \
    1336             :     var = i::Handle<i::WasmType>::cast(this_arg);                    \
    1337             :   }
    1338             : 
    1339    42519285 : void WebAssemblyInstanceGetExports(
    1340             :   const v8::FunctionCallbackInfo<v8::Value>& args) {
    1341             :   v8::Isolate* isolate = args.GetIsolate();
    1342             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1343    85038483 :   HandleScope scope(isolate);
    1344    42519197 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
    1345    42519283 :   EXTRACT_THIS(receiver, WasmInstanceObject);
    1346             :   i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
    1347             :   args.GetReturnValue().Set(Utils::ToLocal(exports_object));
    1348             : }
    1349             : 
    1350        8000 : void WebAssemblyTableGetLength(
    1351             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1352             :   v8::Isolate* isolate = args.GetIsolate();
    1353             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1354       15888 :   HandleScope scope(isolate);
    1355        7888 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
    1356        8000 :   EXTRACT_THIS(receiver, WasmTableObject);
    1357        7888 :   args.GetReturnValue().Set(
    1358       15776 :       v8::Number::New(isolate, receiver->current_length()));
    1359             : }
    1360             : 
    1361             : // WebAssembly.Table.grow(num) -> num
    1362         744 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1363             :   v8::Isolate* isolate = args.GetIsolate();
    1364             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1365        1176 :   HandleScope scope(isolate);
    1366         432 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
    1367         744 :   Local<Context> context = isolate->GetCurrentContext();
    1368         744 :   EXTRACT_THIS(receiver, WasmTableObject);
    1369             : 
    1370             :   uint32_t grow_by;
    1371         648 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) {
    1372             :     return;
    1373             :   }
    1374             : 
    1375             :   i::Handle<i::FixedArray> old_array(receiver->elements(), i_isolate);
    1376         496 :   uint32_t old_size = static_cast<uint32_t>(old_array->length());
    1377             : 
    1378             :   uint64_t max_size64 = receiver->maximum_length().IsUndefined(i_isolate)
    1379             :                             ? i::FLAG_wasm_max_table_size
    1380         936 :                             : receiver->maximum_length()->Number();
    1381         496 :   if (max_size64 > i::FLAG_wasm_max_table_size) {
    1382             :     max_size64 = i::FLAG_wasm_max_table_size;
    1383             :   }
    1384             : 
    1385             :   DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    1386             : 
    1387             :   uint64_t new_size64 =
    1388         496 :       static_cast<uint64_t>(old_size) + static_cast<uint64_t>(grow_by);
    1389         496 :   if (new_size64 > max_size64) {
    1390          64 :     thrower.RangeError("maximum table size exceeded");
    1391          64 :     return;
    1392             :   }
    1393             :   uint32_t new_size = static_cast<uint32_t>(new_size64);
    1394             : 
    1395         432 :   if (new_size != old_size) {
    1396         400 :     receiver->Grow(i_isolate, new_size - old_size);
    1397             : 
    1398             :     i::Handle<i::FixedArray> new_array =
    1399         400 :         i_isolate->factory()->NewFixedArray(new_size);
    1400     9597312 :     for (uint32_t i = 0; i < old_size; ++i) {
    1401     9596912 :       new_array->set(i, old_array->get(i));
    1402             :     }
    1403         400 :     i::Object null = i::ReadOnlyRoots(i_isolate).null_value();
    1404   170590448 :     for (uint32_t i = old_size; i < new_size; ++i) new_array->set(i, null);
    1405         400 :     receiver->set_elements(*new_array);
    1406             :   }
    1407             : 
    1408             :   // TODO(gdeepti): use weak links for instances
    1409             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1410             :   return_value.Set(old_size);
    1411             : }
    1412             : 
    1413             : // WebAssembly.Table.get(num) -> JSFunction
    1414       11080 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1415             :   v8::Isolate* isolate = args.GetIsolate();
    1416             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1417       21144 :   HandleScope scope(isolate);
    1418       10064 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
    1419       11080 :   Local<Context> context = isolate->GetCurrentContext();
    1420       11080 :   EXTRACT_THIS(receiver, WasmTableObject);
    1421             : 
    1422             :   uint32_t index;
    1423       10984 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    1424             :     return;
    1425             :   }
    1426       10512 :   if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) {
    1427         448 :     thrower.RangeError("invalid index %u into function table", index);
    1428         448 :     return;
    1429             :   }
    1430             : 
    1431             :   i::Handle<i::Object> result =
    1432       10064 :       i::WasmTableObject::Get(i_isolate, receiver, index);
    1433             : 
    1434             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1435             :   return_value.Set(Utils::ToLocal(result));
    1436             : }
    1437             : 
    1438             : // WebAssembly.Table.set(num, JSFunction)
    1439        4000 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1440             :   v8::Isolate* isolate = args.GetIsolate();
    1441             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1442        7088 :   HandleScope scope(isolate);
    1443        3088 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
    1444        4000 :   Local<Context> context = isolate->GetCurrentContext();
    1445        4000 :   EXTRACT_THIS(table_object, WasmTableObject);
    1446             : 
    1447             :   // Parameter 0.
    1448             :   uint32_t index;
    1449        3896 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    1450             :     return;
    1451             :   }
    1452        3664 :   if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) {
    1453         328 :     thrower.RangeError("invalid index %u into function table", index);
    1454         328 :     return;
    1455             :   }
    1456             : 
    1457        3336 :   i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
    1458        3336 :   if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) {
    1459         248 :     thrower.TypeError("Argument 1 must be null or a WebAssembly function");
    1460         248 :     return;
    1461             :   }
    1462        3088 :   i::WasmTableObject::Set(i_isolate, table_object, index, element);
    1463             : }
    1464             : 
    1465             : // WebAssembly.Table.type(WebAssembly.Table) -> TableType
    1466          96 : void WebAssemblyTableGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1467             :   v8::Isolate* isolate = args.GetIsolate();
    1468         160 :   HandleScope scope(isolate);
    1469             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1470          64 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()");
    1471             : 
    1472          96 :   auto maybe_table = GetFirstArgumentAsTable(args, &thrower);
    1473         128 :   if (thrower.error()) return;
    1474             :   i::Handle<i::WasmTableObject> table = maybe_table.ToHandleChecked();
    1475          64 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1476             : 
    1477             :   Local<String> element;
    1478          64 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1479          64 :   if (table->type() == i::wasm::ValueType::kWasmAnyFunc) {
    1480             :     element = v8_str(isolate, "anyfunc");
    1481          16 :   } else if (enabled_features.anyref &&
    1482             :              table->type() == i::wasm::ValueType::kWasmAnyRef) {
    1483             :     element = v8_str(isolate, "anyref");
    1484             :   } else {
    1485           0 :     UNREACHABLE();
    1486             :   }
    1487             :   // TODO(aseemgarg): update anyfunc to funcref
    1488         192 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1489         128 :                                v8_str(isolate, "element"), element)
    1490             :            .IsJust()) {
    1491             :     return;
    1492             :   }
    1493             : 
    1494          64 :   uint32_t curr_size = table->current_length();
    1495             :   DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
    1496         192 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1497             :                                v8_str(isolate, "minimum"),
    1498             :                                v8::Integer::NewFromUnsigned(
    1499         192 :                                    isolate, static_cast<uint32_t>(curr_size)))
    1500             :            .IsJust()) {
    1501             :     return;
    1502             :   }
    1503             : 
    1504          64 :   if (!table->maximum_length()->IsUndefined()) {
    1505          32 :     uint64_t max_size = table->maximum_length()->Number();
    1506             :     DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
    1507          96 :     if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1508             :                                  v8_str(isolate, "maximum"),
    1509             :                                  v8::Integer::NewFromUnsigned(
    1510          96 :                                      isolate, static_cast<uint32_t>(max_size)))
    1511             :              .IsJust()) {
    1512             :       return;
    1513             :     }
    1514             :   }
    1515             : 
    1516             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1517             :   return_value.Set(ret);
    1518             : }
    1519             : 
    1520             : // WebAssembly.Memory.grow(num) -> num
    1521         724 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1522             :   v8::Isolate* isolate = args.GetIsolate();
    1523             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1524        1160 :   HandleScope scope(isolate);
    1525         436 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
    1526         724 :   Local<Context> context = isolate->GetCurrentContext();
    1527         724 :   EXTRACT_THIS(receiver, WasmMemoryObject);
    1528             : 
    1529             :   uint32_t delta_size;
    1530         636 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_size)) {
    1531             :     return;
    1532             :   }
    1533             : 
    1534         516 :   uint64_t max_size64 = receiver->maximum_pages();
    1535         516 :   if (max_size64 > uint64_t{i::wasm::max_mem_pages()}) {
    1536         168 :     max_size64 = i::wasm::max_mem_pages();
    1537             :   }
    1538             :   i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);
    1539         516 :   if (!old_buffer->is_growable()) {
    1540           8 :     thrower.RangeError("This memory cannot be grown");
    1541           8 :     return;
    1542             :   }
    1543             : 
    1544             :   DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    1545             : 
    1546         508 :   uint64_t old_size64 = old_buffer->byte_length() / i::wasm::kWasmPageSize;
    1547         508 :   uint64_t new_size64 = old_size64 + static_cast<uint64_t>(delta_size);
    1548             : 
    1549         508 :   if (new_size64 > max_size64) {
    1550          72 :     thrower.RangeError("Maximum memory size exceeded");
    1551          72 :     return;
    1552             :   }
    1553             : 
    1554         436 :   int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_size);
    1555         436 :   if (ret == -1) {
    1556           0 :     thrower.RangeError("Unable to grow instance memory.");
    1557           0 :     return;
    1558             :   }
    1559             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1560             :   return_value.Set(ret);
    1561             : }
    1562             : 
    1563             : // WebAssembly.Memory.buffer -> ArrayBuffer
    1564    10753109 : void WebAssemblyMemoryGetBuffer(
    1565             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1566             :   v8::Isolate* isolate = args.GetIsolate();
    1567             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1568    21506106 :   HandleScope scope(isolate);
    1569    10752997 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
    1570    10753109 :   EXTRACT_THIS(receiver, WasmMemoryObject);
    1571             : 
    1572             :   i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
    1573             :   DCHECK(buffer_obj->IsJSArrayBuffer());
    1574             :   i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
    1575             :                                      i_isolate);
    1576    10752997 :   if (buffer->is_shared()) {
    1577             :     // TODO(gdeepti): More needed here for when cached buffer, and current
    1578             :     // buffer are out of sync, handle that here when bounds checks, and Grow
    1579             :     // are handled correctly.
    1580             :     Maybe<bool> result =
    1581    10750749 :         buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    1582    10750749 :     if (!result.FromJust()) {
    1583             :       thrower.TypeError(
    1584           0 :           "Status of setting SetIntegrityLevel of buffer is false.");
    1585             :     }
    1586             :   }
    1587             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1588             :   return_value.Set(Utils::ToLocal(buffer));
    1589             : }
    1590             : 
    1591             : // WebAssembly.Memory.type(WebAssembly.Memory) -> MemoryType
    1592          80 : void WebAssemblyMemoryGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1593             :   v8::Isolate* isolate = args.GetIsolate();
    1594         128 :   HandleScope scope(isolate);
    1595             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1596          48 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()");
    1597             : 
    1598          80 :   auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
    1599         112 :   if (thrower.error()) return;
    1600             :   i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
    1601          48 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1602             :   i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
    1603             : 
    1604          48 :   size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
    1605             :   DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
    1606         144 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1607             :                                v8_str(isolate, "minimum"),
    1608             :                                v8::Integer::NewFromUnsigned(
    1609         144 :                                    isolate, static_cast<uint32_t>(curr_size)))
    1610             :            .IsJust()) {
    1611             :     return;
    1612             :   }
    1613             : 
    1614          48 :   if (memory->has_maximum_pages()) {
    1615          24 :     uint64_t max_size = memory->maximum_pages();
    1616             :     DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
    1617          72 :     if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1618             :                                  v8_str(isolate, "maximum"),
    1619             :                                  v8::Integer::NewFromUnsigned(
    1620          72 :                                      isolate, static_cast<uint32_t>(max_size)))
    1621             :              .IsJust()) {
    1622             :       return;
    1623             :     }
    1624             :   }
    1625             : 
    1626             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1627             :   return_value.Set(ret);
    1628             : }
    1629             : 
    1630        9224 : void WebAssemblyGlobalGetValueCommon(
    1631             :     const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
    1632             :   v8::Isolate* isolate = args.GetIsolate();
    1633             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1634       18288 :   HandleScope scope(isolate);
    1635        9064 :   ScheduledErrorThrower thrower(i_isolate, name);
    1636        9224 :   EXTRACT_THIS(receiver, WasmGlobalObject);
    1637             : 
    1638             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1639             : 
    1640        9064 :   switch (receiver->type()) {
    1641             :     case i::wasm::kWasmI32:
    1642        6992 :       return_value.Set(receiver->GetI32());
    1643             :       break;
    1644             :     case i::wasm::kWasmI64: {
    1645         112 :       auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1646         112 :       if (enabled_features.bigint) {
    1647         144 :         Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
    1648             : 
    1649             :         return_value.Set(value);
    1650             :       } else {
    1651          40 :         thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
    1652             :       }
    1653             :       break;
    1654             :     }
    1655             :     case i::wasm::kWasmF32:
    1656        9864 :       return_value.Set(receiver->GetF32());
    1657             :       break;
    1658             :     case i::wasm::kWasmF64:
    1659        3504 :       return_value.Set(receiver->GetF64());
    1660             :       break;
    1661             :     case i::wasm::kWasmAnyRef:
    1662             :     case i::wasm::kWasmAnyFunc:
    1663             :     case i::wasm::kWasmExceptRef:
    1664         832 :       return_value.Set(Utils::ToLocal(receiver->GetRef()));
    1665             :       break;
    1666             :     default:
    1667           0 :       UNREACHABLE();
    1668             :   }
    1669             : }
    1670             : 
    1671             : // WebAssembly.Global.valueOf() -> num
    1672        3224 : void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1673        3224 :   return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
    1674             : }
    1675             : 
    1676             : // get WebAssembly.Global.value -> num
    1677        6000 : void WebAssemblyGlobalGetValue(
    1678             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1679        6000 :   return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
    1680             : }
    1681             : 
    1682             : // set WebAssembly.Global.value(num)
    1683        2840 : void WebAssemblyGlobalSetValue(
    1684             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1685             :   v8::Isolate* isolate = args.GetIsolate();
    1686             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1687        5368 :   HandleScope scope(isolate);
    1688        2840 :   Local<Context> context = isolate->GetCurrentContext();
    1689        2528 :   ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
    1690        2840 :   EXTRACT_THIS(receiver, WasmGlobalObject);
    1691             : 
    1692        2768 :   if (!receiver->is_mutable()) {
    1693         216 :     thrower.TypeError("Can't set the value of an immutable global.");
    1694         216 :     return;
    1695             :   }
    1696        2552 :   if (args[0]->IsUndefined()) {
    1697          16 :     thrower.TypeError("Argument 0 is required");
    1698          16 :     return;
    1699             :   }
    1700             : 
    1701        2536 :   switch (receiver->type()) {
    1702             :     case i::wasm::kWasmI32: {
    1703             :       int32_t i32_value = 0;
    1704        2000 :       if (!args[0]->Int32Value(context).To(&i32_value)) return;
    1705        1000 :       receiver->SetI32(i32_value);
    1706             :       break;
    1707             :     }
    1708             :     case i::wasm::kWasmI64: {
    1709          32 :       auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1710          32 :       if (enabled_features.bigint) {
    1711             :         v8::Local<v8::BigInt> bigint_value;
    1712          48 :         if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
    1713          32 :         receiver->SetI64(bigint_value->Int64Value());
    1714             :       } else {
    1715           8 :         thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
    1716             :       }
    1717          24 :       break;
    1718             :     }
    1719             :     case i::wasm::kWasmF32: {
    1720             :       double f64_value = 0;
    1721        1936 :       if (!args[0]->NumberValue(context).To(&f64_value)) return;
    1722        1936 :       receiver->SetF32(static_cast<float>(f64_value));
    1723             :       break;
    1724             :     }
    1725             :     case i::wasm::kWasmF64: {
    1726             :       double f64_value = 0;
    1727         880 :       if (!args[0]->NumberValue(context).To(&f64_value)) return;
    1728         440 :       receiver->SetF64(f64_value);
    1729             :       break;
    1730             :     }
    1731             :     case i::wasm::kWasmAnyRef:
    1732             :     case i::wasm::kWasmExceptRef: {
    1733          72 :       receiver->SetAnyRef(Utils::OpenHandle(*args[0]));
    1734          72 :       break;
    1735             :     }
    1736             :     case i::wasm::kWasmAnyFunc: {
    1737          24 :       if (!receiver->SetAnyFunc(i_isolate, Utils::OpenHandle(*args[0]))) {
    1738             :         thrower.TypeError(
    1739             :             "value of an anyfunc reference must be either null or an "
    1740           8 :             "exported function");
    1741             :       }
    1742             :       break;
    1743             :     }
    1744             :     default:
    1745           0 :       UNREACHABLE();
    1746             :   }
    1747             : }
    1748             : 
    1749             : // WebAssembly.Global.type(WebAssembly.Global) -> GlobalType
    1750          88 : void WebAssemblyGlobalGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1751             :   v8::Isolate* isolate = args.GetIsolate();
    1752         144 :   HandleScope scope(isolate);
    1753             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1754          56 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()");
    1755             : 
    1756          88 :   auto maybe_global = GetFirstArgumentAsGlobal(args, &thrower);
    1757         120 :   if (thrower.error()) return;
    1758             :   i::Handle<i::WasmGlobalObject> global = maybe_global.ToHandleChecked();
    1759          56 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1760             : 
    1761         168 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1762             :                                v8_str(isolate, "mutable"),
    1763         112 :                                v8::Boolean::New(isolate, global->is_mutable()))
    1764             :            .IsJust()) {
    1765             :     return;
    1766             :   }
    1767             : 
    1768             :   Local<String> type;
    1769          56 :   switch (global->type()) {
    1770             :     case i::wasm::kWasmI32: {
    1771             :       type = v8_str(isolate, "i32");
    1772          16 :       break;
    1773             :     }
    1774             :     case i::wasm::kWasmI64: {
    1775             :       type = v8_str(isolate, "i64");
    1776           8 :       break;
    1777             :     }
    1778             :     case i::wasm::kWasmF32: {
    1779             :       type = v8_str(isolate, "f32");
    1780           8 :       break;
    1781             :     }
    1782             :     case i::wasm::kWasmF64: {
    1783             :       type = v8_str(isolate, "f64");
    1784           8 :       break;
    1785             :     }
    1786             :     case i::wasm::kWasmAnyRef: {
    1787             :       type = v8_str(isolate, "anyref");
    1788          16 :       break;
    1789             :     }
    1790             :     default:
    1791           0 :       UNREACHABLE();
    1792             :   }
    1793         168 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1794         112 :                                v8_str(isolate, "value"), type)
    1795             :            .IsJust()) {
    1796             :     return;
    1797             :   }
    1798             : 
    1799             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1800             :   return_value.Set(ret);
    1801             : }
    1802             : 
    1803             : }  // namespace
    1804             : 
    1805             : // TODO(titzer): we use the API to create the function template because the
    1806             : // internal guts are too ugly to replicate here.
    1807     1691374 : static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
    1808             :     i::Isolate* i_isolate, FunctionCallback func) {
    1809             :   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
    1810     1691374 :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
    1811     1691377 :   templ->ReadOnlyPrototype();
    1812     1691375 :   return v8::Utils::OpenHandle(*templ);
    1813             : }
    1814             : 
    1815             : static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
    1816             :     i::Isolate* i_isolate) {
    1817             :   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
    1818      402847 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1819             :   return v8::Utils::OpenHandle(*templ);
    1820             : }
    1821             : 
    1822             : namespace internal {
    1823             : 
    1824     1691377 : Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
    1825             :                               FunctionCallback func) {
    1826     1691377 :   Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
    1827             :   Handle<JSFunction> function =
    1828     3382731 :       ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
    1829             :   DCHECK(function->shared()->HasSharedName());
    1830     1691356 :   return function;
    1831             : }
    1832             : 
    1833     1288741 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
    1834             :                                const char* str, FunctionCallback func,
    1835             :                                int length = 0,
    1836             :                                PropertyAttributes attributes = NONE) {
    1837             :   Handle<String> name = v8_str(isolate, str);
    1838     1288740 :   Handle<JSFunction> function = CreateFunc(isolate, name, func);
    1839             :   function->shared()->set_length(length);
    1840     1288731 :   JSObject::AddProperty(isolate, object, name, function, attributes);
    1841     1288735 :   return function;
    1842             : }
    1843             : 
    1844           0 : Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
    1845             :                                          Handle<JSObject> object,
    1846             :                                          const char* str,
    1847             :                                          FunctionCallback func) {
    1848      402849 :   return InstallFunc(isolate, object, str, func, 1, DONT_ENUM);
    1849             : }
    1850             : 
    1851      322106 : Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
    1852      644218 :   return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
    1853      322112 :       .ToHandleChecked();
    1854             : }
    1855             : 
    1856      241577 : void InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str,
    1857             :                    FunctionCallback func) {
    1858             :   Handle<String> name = v8_str(isolate, str);
    1859             :   Handle<JSFunction> function =
    1860      241579 :       CreateFunc(isolate, GetterName(isolate, name), func);
    1861             : 
    1862      241582 :   Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
    1863             :                                               Utils::ToLocal(function),
    1864      241580 :                                               Local<Function>(), v8::None);
    1865      241582 : }
    1866             : 
    1867       80527 : Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
    1868      161055 :   return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
    1869       80528 :       .ToHandleChecked();
    1870             : }
    1871             : 
    1872       80527 : void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
    1873             :                          const char* str, FunctionCallback getter,
    1874             :                          FunctionCallback setter) {
    1875             :   Handle<String> name = v8_str(isolate, str);
    1876             :   Handle<JSFunction> getter_func =
    1877       80527 :       CreateFunc(isolate, GetterName(isolate, name), getter);
    1878             :   Handle<JSFunction> setter_func =
    1879       80527 :       CreateFunc(isolate, SetterName(isolate, name), setter);
    1880             :   setter_func->shared()->set_length(1);
    1881             : 
    1882             :   v8::PropertyAttribute attributes = v8::None;
    1883             : 
    1884       80528 :   Utils::ToLocal(object)->SetAccessorProperty(
    1885             :       Utils::ToLocal(name), Utils::ToLocal(getter_func),
    1886       80528 :       Utils::ToLocal(setter_func), attributes);
    1887       80528 : }
    1888             : 
    1889             : // Assigns a dummy instance template to the given constructor function. Used to
    1890             : // make sure the implicit receivers for the constructors in this file have an
    1891             : // instance type different from the internal one, they allocate the resulting
    1892             : // object explicitly and ignore implicit receiver.
    1893      402847 : void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
    1894             :   Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
    1895      402848 :   FunctionTemplateInfo::SetInstanceTemplate(
    1896             :       isolate, handle(fun->shared()->get_api_func_data(), isolate),
    1897      402850 :       instance_template);
    1898      402848 : }
    1899             : 
    1900             : // static
    1901     1174826 : void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
    1902     1174826 :   Handle<JSGlobalObject> global = isolate->global_object();
    1903             :   Handle<Context> context(global->native_context(), isolate);
    1904             :   // Install the JS API once only.
    1905             :   Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
    1906     1174829 :   if (!prev->IsUndefined(isolate)) {
    1907             :     DCHECK(prev->IsJSFunction());
    1908     1094302 :     return;
    1909             :   }
    1910             : 
    1911             :   Factory* factory = isolate->factory();
    1912             : 
    1913             :   // Setup WebAssembly
    1914             :   Handle<String> name = v8_str(isolate, "WebAssembly");
    1915             :   NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
    1916       80527 :       name, isolate->strict_function_map(), LanguageMode::kStrict);
    1917       80525 :   Handle<JSFunction> cons = factory->NewFunction(args);
    1918      161054 :   JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
    1919             :   Handle<JSObject> webassembly =
    1920       80528 :       factory->NewJSObject(cons, AllocationType::kOld);
    1921             : 
    1922             :   PropertyAttributes ro_attributes =
    1923             :       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
    1924       80528 :   JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
    1925       80528 :                         name, ro_attributes);
    1926       80528 :   InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
    1927       80528 :   InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
    1928       80527 :   InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
    1929             : 
    1930       80527 :   if (isolate->wasm_streaming_callback() != nullptr) {
    1931             :     InstallFunc(isolate, webassembly, "compileStreaming",
    1932          24 :                 WebAssemblyCompileStreaming, 1);
    1933             :     InstallFunc(isolate, webassembly, "instantiateStreaming",
    1934          24 :                 WebAssemblyInstantiateStreaming, 1);
    1935             :   }
    1936             : 
    1937             :   // Expose the API on the global object if configured to do so.
    1938       80528 :   if (exposed_on_global_object) {
    1939       80503 :     JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM);
    1940             :   }
    1941             : 
    1942             :   // Setup Module
    1943             :   Handle<JSFunction> module_constructor =
    1944             :       InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule);
    1945       80528 :   context->set_wasm_module_constructor(*module_constructor);
    1946       80528 :   SetDummyInstanceTemplate(isolate, module_constructor);
    1947       80527 :   JSFunction::EnsureHasInitialMap(module_constructor);
    1948             :   Handle<JSObject> module_proto(
    1949      161055 :       JSObject::cast(module_constructor->instance_prototype()), isolate);
    1950             :   i::Handle<i::Map> module_map =
    1951       80527 :       isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
    1952       80528 :   JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
    1953             :   InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
    1954       80528 :               1);
    1955             :   InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
    1956       80527 :               1);
    1957             :   InstallFunc(isolate, module_constructor, "customSections",
    1958       80527 :               WebAssemblyModuleCustomSections, 2);
    1959       80528 :   JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
    1960       80527 :                         v8_str(isolate, "WebAssembly.Module"), ro_attributes);
    1961             : 
    1962             :   // Setup Instance
    1963             :   Handle<JSFunction> instance_constructor = InstallConstructorFunc(
    1964             :       isolate, webassembly, "Instance", WebAssemblyInstance);
    1965       80528 :   context->set_wasm_instance_constructor(*instance_constructor);
    1966       80527 :   SetDummyInstanceTemplate(isolate, instance_constructor);
    1967       80527 :   JSFunction::EnsureHasInitialMap(instance_constructor);
    1968             :   Handle<JSObject> instance_proto(
    1969      161054 :       JSObject::cast(instance_constructor->instance_prototype()), isolate);
    1970             :   i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
    1971       80527 :       i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
    1972       80528 :   JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
    1973             :   InstallGetter(isolate, instance_proto, "exports",
    1974       80528 :                 WebAssemblyInstanceGetExports);
    1975       80527 :   JSObject::AddProperty(isolate, instance_proto,
    1976             :                         factory->to_string_tag_symbol(),
    1977       80527 :                         v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
    1978             : 
    1979             :   // The context is not set up completely yet. That's why we cannot use
    1980             :   // {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
    1981       80527 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1982             : 
    1983             :   // Setup Table
    1984             :   Handle<JSFunction> table_constructor =
    1985             :       InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable);
    1986       80525 :   context->set_wasm_table_constructor(*table_constructor);
    1987       80525 :   SetDummyInstanceTemplate(isolate, table_constructor);
    1988       80526 :   JSFunction::EnsureHasInitialMap(table_constructor);
    1989             :   Handle<JSObject> table_proto(
    1990      161052 :       JSObject::cast(table_constructor->instance_prototype()), isolate);
    1991             :   i::Handle<i::Map> table_map =
    1992       80526 :       isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
    1993       80527 :   JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
    1994       80526 :   InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
    1995       80528 :   InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
    1996       80527 :   InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
    1997       80526 :   InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
    1998       80525 :   if (enabled_features.type_reflection) {
    1999          16 :     InstallFunc(isolate, table_constructor, "type", WebAssemblyTableGetType, 1);
    2000             :   }
    2001       80527 :   JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
    2002       80525 :                         v8_str(isolate, "WebAssembly.Table"), ro_attributes);
    2003             : 
    2004             :   // Setup Memory
    2005             :   Handle<JSFunction> memory_constructor =
    2006             :       InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory);
    2007       80528 :   context->set_wasm_memory_constructor(*memory_constructor);
    2008       80528 :   SetDummyInstanceTemplate(isolate, memory_constructor);
    2009       80528 :   JSFunction::EnsureHasInitialMap(memory_constructor);
    2010             :   Handle<JSObject> memory_proto(
    2011      161056 :       JSObject::cast(memory_constructor->instance_prototype()), isolate);
    2012             :   i::Handle<i::Map> memory_map =
    2013       80528 :       isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
    2014       80527 :   JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
    2015       80528 :   InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
    2016       80526 :   InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
    2017       80528 :   if (enabled_features.type_reflection) {
    2018             :     InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryGetType,
    2019          16 :                 1);
    2020             :   }
    2021       80528 :   JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
    2022       80528 :                         v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
    2023             : 
    2024             :   // Setup Global
    2025             :   Handle<JSFunction> global_constructor =
    2026             :       InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal);
    2027       80527 :   context->set_wasm_global_constructor(*global_constructor);
    2028       80527 :   SetDummyInstanceTemplate(isolate, global_constructor);
    2029       80528 :   JSFunction::EnsureHasInitialMap(global_constructor);
    2030             :   Handle<JSObject> global_proto(
    2031      161055 :       JSObject::cast(global_constructor->instance_prototype()), isolate);
    2032             :   i::Handle<i::Map> global_map =
    2033       80527 :       isolate->factory()->NewMap(i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
    2034       80527 :   JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
    2035       80527 :   InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
    2036             :   InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
    2037       80527 :                       WebAssemblyGlobalSetValue);
    2038       80526 :   if (enabled_features.type_reflection) {
    2039             :     InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalGetType,
    2040          16 :                 1);
    2041             :   }
    2042       80527 :   JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
    2043       80527 :                         v8_str(isolate, "WebAssembly.Global"), ro_attributes);
    2044             : 
    2045             :   // Setup Exception
    2046       80527 :   if (enabled_features.eh) {
    2047             :     Handle<JSFunction> exception_constructor = InstallConstructorFunc(
    2048             :         isolate, webassembly, "Exception", WebAssemblyException);
    2049         212 :     context->set_wasm_exception_constructor(*exception_constructor);
    2050         212 :     SetDummyInstanceTemplate(isolate, exception_constructor);
    2051         212 :     JSFunction::EnsureHasInitialMap(exception_constructor);
    2052             :     Handle<JSObject> exception_proto(
    2053         424 :         JSObject::cast(exception_constructor->instance_prototype()), isolate);
    2054             :     i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
    2055         212 :         i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
    2056         212 :     JSFunction::SetInitialMap(exception_constructor, exception_map,
    2057         212 :                               exception_proto);
    2058             :   }
    2059             : 
    2060             :   // Setup errors
    2061             :   Handle<JSFunction> compile_error(
    2062      241581 :       isolate->native_context()->wasm_compile_error_function(), isolate);
    2063       80528 :   JSObject::AddProperty(isolate, webassembly,
    2064             :                         isolate->factory()->CompileError_string(),
    2065       80527 :                         compile_error, DONT_ENUM);
    2066             :   Handle<JSFunction> link_error(
    2067      241584 :       isolate->native_context()->wasm_link_error_function(), isolate);
    2068       80527 :   JSObject::AddProperty(isolate, webassembly,
    2069             :                         isolate->factory()->LinkError_string(), link_error,
    2070       80528 :                         DONT_ENUM);
    2071             :   Handle<JSFunction> runtime_error(
    2072      241580 :       isolate->native_context()->wasm_runtime_error_function(), isolate);
    2073       80528 :   JSObject::AddProperty(isolate, webassembly,
    2074             :                         isolate->factory()->RuntimeError_string(),
    2075       80526 :                         runtime_error, DONT_ENUM);
    2076             : }
    2077             : 
    2078             : #undef ASSIGN
    2079             : #undef EXTRACT_THIS
    2080             : 
    2081             : }  // namespace internal
    2082      120216 : }  // namespace v8

Generated by: LCOV version 1.10