LCOV - code coverage report
Current view: top level - src/wasm - wasm-js.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 772 823 93.8 %
Date: 2019-04-17 Functions: 76 91 83.5 %

          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         192 : class WasmStreaming::WasmStreamingImpl {
      37             :  public:
      38          96 :   WasmStreamingImpl(
      39             :       Isolate* isolate,
      40             :       std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
      41          96 :       : isolate_(isolate), resolver_(std::move(resolver)) {
      42          96 :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
      43          96 :     auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
      44         288 :     streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
      45             :         i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
      46             :         resolver_);
      47          96 :   }
      48             : 
      49             :   void OnBytesReceived(const uint8_t* bytes, size_t size) {
      50          64 :     streaming_decoder_->OnBytesReceived(i::VectorOf(bytes, size));
      51             :   }
      52          64 :   void Finish() { streaming_decoder_->Finish(); }
      53             : 
      54          24 :   void Abort(MaybeLocal<Value> exception) {
      55          24 :     i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
      56          24 :     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          24 :     if (exception.IsEmpty()) return;
      62             : 
      63             :     resolver_->OnCompilationFailed(
      64          40 :         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          24 :   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          92 : 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          92 :   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   109824010 : 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    54912005 :   if (isolate()->has_scheduled_exception()) {
     163        1772 :     Reset();
     164    54910233 :   } else if (isolate()->has_pending_exception()) {
     165          48 :     Reset();
     166          48 :     isolate()->OptionalRescheduleException(false);
     167    54910185 :   } else if (error()) {
     168       47384 :     isolate()->ScheduleThrow(*Reify());
     169             :   }
     170    54912006 : }
     171             : 
     172             : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
     173     2174401 :   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      392035 : 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      282759 : 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      282759 :   if (source->IsArrayBuffer()) {
     207             :     // A raw array buffer was passed.
     208             :     Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
     209      253864 :     ArrayBuffer::Contents contents = buffer->GetContents();
     210             : 
     211             :     start = reinterpret_cast<const uint8_t*>(contents.Data());
     212             :     length = contents.ByteLength();
     213      253864 :     *is_shared = buffer->IsSharedArrayBuffer();
     214       28896 :   } else if (source->IsTypedArray()) {
     215             :     // A TypedArray was passed.
     216             :     Local<TypedArray> array = Local<TypedArray>::Cast(source);
     217       28416 :     Local<ArrayBuffer> buffer = array->Buffer();
     218             : 
     219       28413 :     ArrayBuffer::Contents contents = buffer->GetContents();
     220             : 
     221             :     start =
     222       28416 :         reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
     223       28416 :     length = array->ByteLength();
     224       28416 :     *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      282761 :   if (length == 0) {
     230         780 :     thrower->CompileError("BufferSource argument is empty");
     231             :   }
     232      282761 :   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      282761 :   if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
     237      281957 :   return i::wasm::ModuleWireBytes(start, start + length);
     238             : }
     239             : 
     240      132581 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
     241             :                                                 ErrorThrower* thrower) {
     242      132581 :   if (arg->IsUndefined()) return {};
     243             : 
     244      125039 :   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      124799 :   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         848 :   AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
     258        1696 :       : promise_(isolate->global_handles()->Create(*promise)) {
     259             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     260         848 :                                              kGlobalPromiseHandle);
     261         848 :   }
     262             : 
     263        1696 :   ~AsyncCompilationResolver() override {
     264         848 :     i::GlobalHandles::Destroy(promise_.location());
     265         808 :   }
     266             : 
     267         349 :   void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
     268         349 :     if (finished_) return;
     269         349 :     finished_ = true;
     270             :     i::MaybeHandle<i::Object> promise_result =
     271         349 :         i::JSPromise::Resolve(promise_, result);
     272         349 :     CHECK_EQ(promise_result.is_null(),
     273             :              promise_->GetIsolate()->has_pending_exception());
     274             :   }
     275             : 
     276         484 :   void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
     277         484 :     if (finished_) return;
     278         484 :     finished_ = true;
     279             :     i::MaybeHandle<i::Object> promise_result =
     280         484 :         i::JSPromise::Reject(promise_, error_reason);
     281         484 :     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        7382 :   InstantiateModuleResultResolver(i::Isolate* isolate,
     300             :                                   i::Handle<i::JSPromise> promise)
     301       14764 :       : promise_(isolate->global_handles()->Create(*promise)) {
     302             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     303        7382 :                                              kGlobalPromiseHandle);
     304        7382 :   }
     305             : 
     306       14764 :   ~InstantiateModuleResultResolver() override {
     307        7382 :     i::GlobalHandles::Destroy(promise_.location());
     308        7382 :   }
     309             : 
     310         120 :   void OnInstantiationSucceeded(
     311             :       i::Handle<i::WasmInstanceObject> instance) override {
     312             :     i::MaybeHandle<i::Object> promise_result =
     313         120 :         i::JSPromise::Resolve(promise_, instance);
     314         120 :     CHECK_EQ(promise_result.is_null(),
     315             :              promise_->GetIsolate()->has_pending_exception());
     316         120 :   }
     317             : 
     318        5362 :   void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
     319             :     i::MaybeHandle<i::Object> promise_result =
     320        5362 :         i::JSPromise::Reject(promise_, error_reason);
     321        5362 :     CHECK_EQ(promise_result.is_null(),
     322             :              promise_->GetIsolate()->has_pending_exception());
     323        5362 :   }
     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        1852 :   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        7408 :         module_(isolate_->global_handles()->Create(*module)) {
     345             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     346        1852 :                                              kGlobalPromiseHandle);
     347             :     i::GlobalHandles::AnnotateStrongRetainer(module_.location(),
     348        1852 :                                              kGlobalModuleHandle);
     349        1852 :   }
     350             : 
     351        3704 :   ~InstantiateBytesResultResolver() override {
     352        1852 :     i::GlobalHandles::Destroy(promise_.location());
     353        1852 :     i::GlobalHandles::Destroy(module_.location());
     354        1852 :   }
     355             : 
     356        1204 :   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        1204 :         isolate_->factory()->NewJSObject(isolate_->object_function());
     362             : 
     363             :     i::Handle<i::String> instance_name =
     364        1204 :         isolate_->factory()
     365        2408 :             ->NewStringFromOneByte(i::StaticCharVector("instance"))
     366             :             .ToHandleChecked();
     367             : 
     368             :     i::Handle<i::String> module_name =
     369        1204 :         isolate_->factory()
     370        2408 :             ->NewStringFromOneByte(i::StaticCharVector("module"))
     371             :             .ToHandleChecked();
     372             : 
     373        2408 :     i::JSObject::AddProperty(isolate_, result, instance_name, instance,
     374        1204 :                              i::NONE);
     375        1204 :     i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);
     376             : 
     377             :     i::MaybeHandle<i::Object> promise_result =
     378        1204 :         i::JSPromise::Resolve(promise_, result);
     379        2408 :     CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
     380        1204 :   }
     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        1900 :   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         784 :                            : isolate_->global_handles()->Create(
     415        5700 :                                  *maybe_imports.ToHandleChecked())) {
     416             :     i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
     417        1900 :                                              kGlobalPromiseHandle);
     418        1900 :     if (!maybe_imports_.is_null()) {
     419             :       i::GlobalHandles::AnnotateStrongRetainer(
     420         784 :           maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle);
     421             :     }
     422        1900 :   }
     423             : 
     424        3800 :   ~AsyncInstantiateCompileResultResolver() override {
     425        1900 :     i::GlobalHandles::Destroy(promise_.location());
     426        1900 :     if (!maybe_imports_.is_null()) {
     427         784 :       i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
     428             :     }
     429        3800 :   }
     430             : 
     431        1852 :   void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
     432        1852 :     if (finished_) return;
     433        1852 :     finished_ = true;
     434        3704 :     isolate_->wasm_engine()->AsyncInstantiate(
     435             :         isolate_,
     436        3704 :         base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
     437             :                                                           result),
     438        1852 :         result, maybe_imports_);
     439             :   }
     440             : 
     441          48 :   void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
     442          48 :     if (finished_) return;
     443          48 :     finished_ = true;
     444             :     i::MaybeHandle<i::Object> promise_result =
     445          48 :         i::JSPromise::Reject(promise_, error_reason);
     446          96 :     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       24564 : bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context,
     474             :                    ErrorThrower* thrower, uint32_t* res) {
     475             :   double double_number;
     476             : 
     477       49128 :   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       24500 :   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       23924 :   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       23556 :   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       23276 :   *res = static_cast<uint32_t>(double_number);
     499       23276 :   return true;
     500             : }
     501             : }  // namespace
     502             : 
     503             : // WebAssembly.compile(bytes) -> Promise
     504         808 : 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        1372 :   HandleScope scope(isolate);
     509         564 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
     510             : 
     511        1616 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     512          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     513             :   }
     514             : 
     515         808 :   Local<Context> context = isolate->GetCurrentContext();
     516        1860 :   ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
     517         808 :   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        1616 :       new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
     523             : 
     524         808 :   bool is_shared = false;
     525         808 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     526         808 :   if (thrower.error()) {
     527         244 :     resolver->OnCompilationFailed(thrower.Reify());
     528             :     return;
     529             :   }
     530             :   // Asynchronous compilation handles copying wire bytes if necessary.
     531         564 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     532        1128 :   i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
     533         564 :                                          std::move(resolver), bytes, is_shared);
     534             : }
     535             : 
     536          56 : void WasmStreamingCallbackForTesting(
     537             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     538             :   v8::Isolate* isolate = args.GetIsolate();
     539             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     540             : 
     541         112 :   HandleScope scope(isolate);
     542          56 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
     543             : 
     544             :   std::shared_ptr<v8::WasmStreaming> streaming =
     545          56 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
     546             : 
     547          56 :   bool is_shared = false;
     548             :   i::wasm::ModuleWireBytes bytes =
     549          56 :       GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     550          56 :   if (thrower.error()) {
     551           0 :     streaming->Abort(Utils::ToLocal(thrower.Reify()));
     552             :     return;
     553             :   }
     554             :   streaming->OnBytesReceived(bytes.start(), bytes.length());
     555             :   streaming->Finish();
     556          56 :   CHECK(!thrower.error());
     557             : }
     558             : 
     559          16 : void WasmStreamingPromiseFailedCallback(
     560             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     561             :   std::shared_ptr<v8::WasmStreaming> streaming =
     562          16 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
     563             :   streaming->Abort(args[0]);
     564          16 : }
     565             : 
     566             : // WebAssembly.compileStreaming(Promise<Response>) -> Promise
     567          40 : void WebAssemblyCompileStreaming(
     568             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     569             :   v8::Isolate* isolate = args.GetIsolate();
     570          40 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     571          80 :   HandleScope scope(isolate);
     572          80 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
     573          40 :   Local<Context> context = isolate->GetCurrentContext();
     574             : 
     575             :   // Create and assign the return value of this function.
     576          80 :   ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
     577          40 :   Local<Promise> promise = result_resolver->GetPromise();
     578             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     579             :   return_value.Set(promise);
     580             : 
     581             :   // Prepare the CompilationResultResolver for the compilation.
     582             :   auto resolver = std::make_shared<AsyncCompilationResolver>(
     583          80 :       i_isolate, Utils::OpenHandle(*promise));
     584             : 
     585          80 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     586           0 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     587           0 :     resolver->OnCompilationFailed(thrower.Reify());
     588           0 :     return;
     589             :   }
     590             : 
     591             :   // Allocate the streaming decoder in a Managed so we can pass it to the
     592             :   // embedder.
     593             :   i::Handle<i::Managed<WasmStreaming>> data =
     594             :       i::Managed<WasmStreaming>::Allocate(
     595             :           i_isolate, 0,
     596          80 :           base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
     597          40 :                                                               resolver));
     598             : 
     599             :   DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
     600          80 :   ASSIGN(
     601             :       v8::Function, compile_callback,
     602             :       v8::Function::New(context, i_isolate->wasm_streaming_callback(),
     603             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     604          80 :   ASSIGN(
     605             :       v8::Function, reject_callback,
     606             :       v8::Function::New(context, WasmStreamingPromiseFailedCallback,
     607             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     608             : 
     609             :   // The parameter may be of type {Response} or of type {Promise<Response>}.
     610             :   // Treat either case of parameter as Promise.resolve(parameter)
     611             :   // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
     612             : 
     613             :   // Ending with:
     614             :   //    return Promise.resolve(parameter).then(compile_callback);
     615          80 :   ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
     616          80 :   if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
     617             : 
     618             :   // We do not have any use of the result here. The {compile_callback} will
     619             :   // start streaming compilation, which will eventually resolve the promise we
     620             :   // set as result value.
     621          80 :   USE(input_resolver->GetPromise()->Then(context, compile_callback,
     622             :                                          reject_callback));
     623             : }
     624             : 
     625             : // WebAssembly.validate(bytes) -> bool
     626      128040 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
     627             :   v8::Isolate* isolate = args.GetIsolate();
     628             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     629      255888 :   HandleScope scope(isolate);
     630      127848 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
     631             : 
     632      128040 :   bool is_shared = false;
     633      128040 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     634             : 
     635             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     636             : 
     637      128040 :   if (thrower.error()) {
     638         192 :     if (thrower.wasm_error()) thrower.Reset();  // Clear error.
     639             :     return_value.Set(v8::False(isolate));
     640         192 :     return;
     641             :   }
     642             : 
     643      127848 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     644             :   bool validated = false;
     645      127848 :   if (is_shared) {
     646             :     // Make a copy of the wire bytes to avoid concurrent modification.
     647           0 :     std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
     648             :     memcpy(copy.get(), bytes.start(), bytes.length());
     649             :     i::wasm::ModuleWireBytes bytes_copy(copy.get(),
     650           0 :                                         copy.get() + bytes.length());
     651             :     validated = i_isolate->wasm_engine()->SyncValidate(
     652           0 :         i_isolate, enabled_features, bytes_copy);
     653             :   } else {
     654             :     // The wire bytes are not shared, OK to use them directly.
     655             :     validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
     656      127848 :                                                        enabled_features, bytes);
     657             :   }
     658             : 
     659             :   return_value.Set(Boolean::New(isolate, validated));
     660             : }
     661             : 
     662             : // new WebAssembly.Module(bytes) -> WebAssembly.Module
     663      151969 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
     664             :   v8::Isolate* isolate = args.GetIsolate();
     665             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     666      168889 :   if (i_isolate->wasm_module_callback()(args)) return;
     667             : 
     668      287014 :   HandleScope scope(isolate);
     669      135053 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
     670             : 
     671      151964 :   if (!args.IsConstructCall()) {
     672          32 :     thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
     673          32 :     return;
     674             :   }
     675      303862 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     676          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     677          24 :     return;
     678             :   }
     679             : 
     680      151908 :   bool is_shared = false;
     681      151908 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     682             : 
     683      151909 :   if (thrower.error()) {
     684             :     return;
     685             :   }
     686      151645 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     687             :   i::MaybeHandle<i::Object> module_obj;
     688      151641 :   if (is_shared) {
     689             :     // Make a copy of the wire bytes to avoid concurrent modification.
     690           0 :     std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
     691             :     memcpy(copy.get(), bytes.start(), bytes.length());
     692             :     i::wasm::ModuleWireBytes bytes_copy(copy.get(),
     693           0 :                                         copy.get() + bytes.length());
     694             :     module_obj = i_isolate->wasm_engine()->SyncCompile(
     695           0 :         i_isolate, enabled_features, &thrower, bytes_copy);
     696             :   } else {
     697             :     // The wire bytes are not shared, OK to use them directly.
     698             :     module_obj = i_isolate->wasm_engine()->SyncCompile(
     699      151641 :         i_isolate, enabled_features, &thrower, bytes);
     700             :   }
     701             : 
     702      151644 :   if (module_obj.is_null()) return;
     703             : 
     704             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     705             :   return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
     706             : }
     707             : 
     708             : // WebAssembly.Module.imports(module) -> Array<Import>
     709         248 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
     710         392 :   HandleScope scope(args.GetIsolate());
     711             :   v8::Isolate* isolate = args.GetIsolate();
     712             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     713         144 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
     714             : 
     715         248 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     716         352 :   if (thrower.error()) return;
     717         144 :   auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
     718             :   args.GetReturnValue().Set(Utils::ToLocal(imports));
     719             : }
     720             : 
     721             : // WebAssembly.Module.exports(module) -> Array<Export>
     722         240 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
     723         376 :   HandleScope scope(args.GetIsolate());
     724             :   v8::Isolate* isolate = args.GetIsolate();
     725             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     726         136 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
     727             : 
     728         240 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     729         344 :   if (thrower.error()) return;
     730         136 :   auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
     731             :   args.GetReturnValue().Set(Utils::ToLocal(exports));
     732             : }
     733             : 
     734             : // WebAssembly.Module.customSections(module, name) -> Array<Section>
     735         376 : void WebAssemblyModuleCustomSections(
     736             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     737         624 :   HandleScope scope(args.GetIsolate());
     738             :   v8::Isolate* isolate = args.GetIsolate();
     739             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     740             :   ScheduledErrorThrower thrower(i_isolate,
     741         248 :                                 "WebAssembly.Module.customSections()");
     742             : 
     743         376 :   auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
     744         504 :   if (thrower.error()) return;
     745             : 
     746         264 :   if (args[1]->IsUndefined()) {
     747           8 :     thrower.TypeError("Argument 1 is required");
     748           8 :     return;
     749             :   }
     750             : 
     751             :   i::MaybeHandle<i::Object> maybe_name =
     752         256 :       i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
     753             :   i::Handle<i::Object> name;
     754         256 :   if (!maybe_name.ToHandle(&name)) return;
     755             :   auto custom_sections =
     756             :       i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
     757         248 :                                  i::Handle<i::String>::cast(name), &thrower);
     758         248 :   if (thrower.error()) return;
     759             :   args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
     760             : }
     761             : 
     762      129824 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
     763             :                                              Local<Value> module,
     764             :                                              Local<Value> ffi) {
     765             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     766             : 
     767             :   i::MaybeHandle<i::Object> instance_object;
     768             :   {
     769      129746 :     ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
     770             : 
     771             :     // TODO(ahaas): These checks on the module should not be necessary here They
     772             :     // are just a workaround for https://crbug.com/837417.
     773             :     i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
     774      129824 :     if (!module_obj->IsWasmModuleObject()) {
     775           0 :       thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
     776           0 :       return {};
     777             :     }
     778             : 
     779             :     i::MaybeHandle<i::JSReceiver> maybe_imports =
     780      129824 :         GetValueAsImports(ffi, &thrower);
     781      129825 :     if (thrower.error()) return {};
     782             : 
     783             :     instance_object = i_isolate->wasm_engine()->SyncInstantiate(
     784             :         i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
     785      129745 :         maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
     786             :   }
     787             : 
     788             :   DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
     789      129747 :   if (instance_object.is_null()) return {};
     790      128135 :   return Utils::ToLocal(instance_object.ToHandleChecked());
     791             : }
     792             : 
     793             : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
     794      130002 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
     795             :   Isolate* isolate = args.GetIsolate();
     796             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     797             :   i_isolate->CountUsage(
     798      130002 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     799             : 
     800      259827 :   HandleScope scope(args.GetIsolate());
     801      130176 :   if (i_isolate->wasm_instance_callback()(args)) return;
     802             : 
     803      129827 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
     804      129993 :   if (!args.IsConstructCall()) {
     805          24 :     thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
     806          24 :     return;
     807             :   }
     808             : 
     809      129969 :   GetFirstArgumentAsModule(args, &thrower);
     810      129968 :   if (thrower.error()) return;
     811             : 
     812             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     813             :   // We'll check for that in WebAssemblyInstantiateImpl.
     814      129825 :   Local<Value> data = args[1];
     815             : 
     816             :   Local<Value> instance;
     817      259652 :   if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
     818             :     args.GetReturnValue().Set(instance);
     819             :   }
     820             : }
     821             : 
     822          56 : void WebAssemblyInstantiateStreaming(
     823             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     824          56 :   v8::Isolate* isolate = args.GetIsolate();
     825             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     826             :   i_isolate->CountUsage(
     827          56 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     828             : 
     829         112 :   HandleScope scope(isolate);
     830          56 :   Local<Context> context = isolate->GetCurrentContext();
     831             :   ScheduledErrorThrower thrower(i_isolate,
     832          56 :                                 "WebAssembly.instantiateStreaming()");
     833             : 
     834             :   // Create and assign the return value of this function.
     835         112 :   ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
     836          56 :   Local<Promise> promise = result_resolver->GetPromise();
     837             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
     838             :   return_value.Set(promise);
     839             : 
     840             :   // Create an InstantiateResultResolver in case there is an issue with the
     841             :   // passed parameters.
     842             :   std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
     843             :       new InstantiateModuleResultResolver(i_isolate,
     844          56 :                                           Utils::OpenHandle(*promise)));
     845             : 
     846         112 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     847           0 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     848           0 :     resolver->OnInstantiationFailed(thrower.Reify());
     849           0 :     return;
     850             :   }
     851             : 
     852             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     853          56 :   Local<Value> ffi = args[1];
     854             :   i::MaybeHandle<i::JSReceiver> maybe_imports =
     855          56 :       GetValueAsImports(ffi, &thrower);
     856             : 
     857          56 :   if (thrower.error()) {
     858           0 :     resolver->OnInstantiationFailed(thrower.Reify());
     859           0 :     return;
     860             :   }
     861             : 
     862             :   // We start compilation now, we have no use for the
     863             :   // {InstantiationResultResolver}.
     864             :   resolver.reset();
     865             : 
     866             :   std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
     867             :       new AsyncInstantiateCompileResultResolver(
     868         112 :           i_isolate, Utils::OpenHandle(*promise), maybe_imports));
     869             : 
     870             :   // Allocate the streaming decoder in a Managed so we can pass it to the
     871             :   // embedder.
     872             :   i::Handle<i::Managed<WasmStreaming>> data =
     873             :       i::Managed<WasmStreaming>::Allocate(
     874             :           i_isolate, 0,
     875         112 :           base::make_unique<WasmStreaming::WasmStreamingImpl>(
     876          56 :               isolate, compilation_resolver));
     877             : 
     878             :   DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
     879         112 :   ASSIGN(
     880             :       v8::Function, compile_callback,
     881             :       v8::Function::New(context, i_isolate->wasm_streaming_callback(),
     882             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     883         112 :   ASSIGN(
     884             :       v8::Function, reject_callback,
     885             :       v8::Function::New(context, WasmStreamingPromiseFailedCallback,
     886             :                         Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
     887             : 
     888             :   // The parameter may be of type {Response} or of type {Promise<Response>}.
     889             :   // Treat either case of parameter as Promise.resolve(parameter)
     890             :   // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
     891             : 
     892             :   // Ending with:
     893             :   //    return Promise.resolve(parameter).then(compile_callback);
     894         112 :   ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
     895         112 :   if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
     896             : 
     897             :   // We do not have any use of the result here. The {compile_callback} will
     898             :   // start streaming compilation, which will eventually resolve the promise we
     899             :   // set as result value.
     900         112 :   USE(input_resolver->GetPromise()->Then(context, compile_callback,
     901             :                                          reject_callback));
     902             : }
     903             : 
     904             : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
     905             : // WebAssembly.instantiate(bytes, imports) ->
     906             : //     {module: WebAssembly.Module, instance: WebAssembly.Instance}
     907        7326 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
     908             :   v8::Isolate* isolate = args.GetIsolate();
     909             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
     910             :   i_isolate->CountUsage(
     911        7326 :       v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
     912             : 
     913        1820 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
     914             : 
     915        9146 :   HandleScope scope(isolate);
     916             : 
     917        7326 :   Local<Context> context = isolate->GetCurrentContext();
     918             : 
     919       20158 :   ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
     920        7326 :   Local<Promise> promise = promise_resolver->GetPromise();
     921             :   args.GetReturnValue().Set(promise);
     922             : 
     923             :   std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
     924             :       new InstantiateModuleResultResolver(i_isolate,
     925        7326 :                                           Utils::OpenHandle(*promise)));
     926             : 
     927             :   Local<Value> first_arg_value = args[0];
     928             :   i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
     929        7326 :   if (!first_arg->IsJSObject()) {
     930             :     thrower.TypeError(
     931        4626 :         "Argument 0 must be a buffer source or a WebAssembly.Module object");
     932        4626 :     resolver->OnInstantiationFailed(thrower.Reify());
     933        4626 :     return;
     934             :   }
     935             : 
     936             :   // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
     937        2700 :   Local<Value> ffi = args[1];
     938             :   i::MaybeHandle<i::JSReceiver> maybe_imports =
     939        2700 :       GetValueAsImports(ffi, &thrower);
     940             : 
     941        2700 :   if (thrower.error()) {
     942         160 :     resolver->OnInstantiationFailed(thrower.Reify());
     943         160 :     return;
     944             :   }
     945             : 
     946        2540 :   if (first_arg->IsWasmModuleObject()) {
     947             :     i::Handle<i::WasmModuleObject> module_obj =
     948         592 :         i::Handle<i::WasmModuleObject>::cast(first_arg);
     949             : 
     950         592 :     i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
     951         592 :                                                module_obj, maybe_imports);
     952             :     return;
     953             :   }
     954             : 
     955        1948 :   bool is_shared = false;
     956        1948 :   auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
     957        1948 :   if (thrower.error()) {
     958         104 :     resolver->OnInstantiationFailed(thrower.Reify());
     959         104 :     return;
     960             :   }
     961             : 
     962             :   // We start compilation now, we have no use for the
     963             :   // {InstantiationResultResolver}.
     964             :   resolver.reset();
     965             : 
     966             :   std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
     967             :       new AsyncInstantiateCompileResultResolver(
     968        3688 :           i_isolate, Utils::OpenHandle(*promise), maybe_imports));
     969             : 
     970             :   // The first parameter is a buffer source, we have to check if we are allowed
     971             :   // to compile it.
     972        3688 :   if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
     973          24 :     thrower.CompileError("Wasm code generation disallowed by embedder");
     974          24 :     compilation_resolver->OnCompilationFailed(thrower.Reify());
     975             :     return;
     976             :   }
     977             : 
     978             :   // Asynchronous compilation handles copying wire bytes if necessary.
     979        1820 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
     980        3640 :   i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
     981             :                                          std::move(compilation_resolver), bytes,
     982        1820 :                                          is_shared);
     983             : }
     984             : 
     985        8824 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
     986             :                         Local<Context> context, v8::Local<v8::Value> value,
     987             :                         i::Handle<i::String> property_name, int64_t* result,
     988             :                         int64_t lower_bound, uint64_t upper_bound) {
     989             :   uint32_t number;
     990        8824 :   if (!EnforceUint32(property_name, value, context, thrower, &number)) {
     991             :     return false;
     992             :   }
     993        8512 :   if (number < lower_bound) {
     994             :     thrower->RangeError("Property '%s': value %" PRIu32
     995             :                         " is below the lower bound %" PRIx64,
     996         144 :                         property_name->ToCString().get(), number, lower_bound);
     997             :     return false;
     998             :   }
     999        8464 :   if (number > upper_bound) {
    1000             :     thrower->RangeError("Property '%s': value %" PRIu32
    1001             :                         " is above the upper bound %" PRIu64,
    1002         192 :                         property_name->ToCString().get(), number, upper_bound);
    1003             :     return false;
    1004             :   }
    1005             : 
    1006        8400 :   *result = static_cast<int64_t>(number);
    1007             :   return true;
    1008             : }
    1009             : 
    1010       12878 : bool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
    1011             :                                 Local<Context> context,
    1012             :                                 Local<v8::Object> object,
    1013             :                                 Local<String> property, bool* has_property,
    1014             :                                 int64_t* result, int64_t lower_bound,
    1015             :                                 uint64_t upper_bound) {
    1016             :   v8::Local<v8::Value> value;
    1017       25756 :   if (!object->Get(context, property).ToLocal(&value)) {
    1018             :     return false;
    1019             :   }
    1020             : 
    1021             :   // Web IDL: dictionary presence
    1022             :   // https://heycam.github.io/webidl/#dfn-present
    1023       12878 :   if (value->IsUndefined()) {
    1024        4054 :     if (has_property != nullptr) *has_property = false;
    1025             :     return true;
    1026             :   }
    1027             : 
    1028        8824 :   if (has_property != nullptr) *has_property = true;
    1029        8824 :   i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property);
    1030             : 
    1031             :   return GetIntegerProperty(isolate, thrower, context, value, property_name,
    1032        8824 :                             result, lower_bound, upper_bound);
    1033             : }
    1034             : 
    1035             : // Fetch 'initial' or 'minimum' property from object. If both are provided,
    1036             : // 'initial' is used.
    1037             : // TODO(aseemgarg): change behavior when the following bug is resolved:
    1038             : // https://github.com/WebAssembly/js-types/issues/6
    1039        6543 : bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
    1040             :                                  Local<Context> context,
    1041             :                                  Local<v8::Object> object, int64_t* result,
    1042             :                                  int64_t lower_bound, uint64_t upper_bound) {
    1043        6543 :   bool has_initial = false;
    1044        6543 :   if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
    1045             :                                   v8_str(isolate, "initial"), &has_initial,
    1046             :                                   result, lower_bound, upper_bound)) {
    1047             :     return false;
    1048             :   }
    1049        6335 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1050        6335 :   if (!has_initial && enabled_features.type_reflection) {
    1051          32 :     if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
    1052             :                                     v8_str(isolate, "minimum"), &has_initial,
    1053             :                                     result, lower_bound, upper_bound)) {
    1054             :       return false;
    1055             :     }
    1056             :   }
    1057        6335 :   if (!has_initial) {
    1058             :     // TODO(aseemgarg): update error message when the spec issue is resolved.
    1059          32 :     thrower->TypeError("Property 'initial' is required");
    1060          32 :     return false;
    1061             :   }
    1062             :   return true;
    1063             : }
    1064             : 
    1065             : // new WebAssembly.Table(args) -> WebAssembly.Table
    1066        2164 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1067             :   v8::Isolate* isolate = args.GetIsolate();
    1068             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1069        3872 :   HandleScope scope(isolate);
    1070        1708 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
    1071        2164 :   if (!args.IsConstructCall()) {
    1072          24 :     thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
    1073          24 :     return;
    1074             :   }
    1075        2140 :   if (!args[0]->IsObject()) {
    1076         120 :     thrower.TypeError("Argument 0 must be a table descriptor");
    1077         120 :     return;
    1078             :   }
    1079        2020 :   Local<Context> context = isolate->GetCurrentContext();
    1080             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1081             :   i::wasm::ValueType type;
    1082             :   // The descriptor's 'element'.
    1083             :   {
    1084             :     v8::MaybeLocal<v8::Value> maybe =
    1085        2020 :         descriptor->Get(context, v8_str(isolate, "element"));
    1086             :     v8::Local<v8::Value> value;
    1087        2108 :     if (!maybe.ToLocal(&value)) return;
    1088             :     v8::Local<v8::String> string;
    1089        4040 :     if (!value->ToString(context).ToLocal(&string)) return;
    1090        2020 :     auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1091        2020 :     if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
    1092             :       type = i::wasm::kWasmAnyFunc;
    1093         136 :     } else if (enabled_features.anyref &&
    1094          24 :                string->StringEquals(v8_str(isolate, "anyref"))) {
    1095             :       type = i::wasm::kWasmAnyRef;
    1096             :     } else {
    1097          88 :       thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
    1098          88 :       return;
    1099             :     }
    1100             :   }
    1101             : 
    1102        1932 :   int64_t initial = 0;
    1103        1932 :   if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
    1104             :                                    &initial, 0,
    1105        1932 :                                    i::wasm::max_table_init_entries())) {
    1106             :     return;
    1107             :   }
    1108             :   // The descriptor's 'maximum'.
    1109        1828 :   int64_t maximum = -1;
    1110        1828 :   bool has_maximum = true;
    1111        3656 :   if (!GetOptionalIntegerProperty(
    1112             :           isolate, &thrower, context, descriptor, v8_str(isolate, "maximum"),
    1113        1828 :           &has_maximum, &maximum, initial, i::wasm::max_table_init_entries())) {
    1114             :     return;
    1115             :   }
    1116             : 
    1117             :   i::Handle<i::FixedArray> fixed_array;
    1118             :   i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
    1119             :       i_isolate, type, static_cast<uint32_t>(initial), has_maximum,
    1120        1708 :       static_cast<uint32_t>(maximum), &fixed_array);
    1121             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1122             :   return_value.Set(Utils::ToLocal(table_obj));
    1123             : }
    1124             : 
    1125        4755 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1126             :   v8::Isolate* isolate = args.GetIsolate();
    1127             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1128        9118 :   HandleScope scope(isolate);
    1129        4363 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
    1130        4755 :   if (!args.IsConstructCall()) {
    1131          24 :     thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
    1132          24 :     return;
    1133             :   }
    1134        4731 :   if (!args[0]->IsObject()) {
    1135         120 :     thrower.TypeError("Argument 0 must be a memory descriptor");
    1136         120 :     return;
    1137             :   }
    1138        4611 :   Local<Context> context = isolate->GetCurrentContext();
    1139             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1140             : 
    1141        4611 :   int64_t initial = 0;
    1142        4611 :   if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
    1143        4611 :                                    &initial, 0, i::wasm::max_mem_pages())) {
    1144             :     return;
    1145             :   }
    1146             :   // The descriptor's 'maximum'.
    1147        4475 :   int64_t maximum = -1;
    1148        8950 :   if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
    1149             :                                   v8_str(isolate, "maximum"), nullptr, &maximum,
    1150             :                                   initial, i::wasm::kSpecMaxWasmMemoryPages)) {
    1151             :     return;
    1152             :   }
    1153             : 
    1154             :   bool is_shared_memory = false;
    1155        4379 :   auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1156        4379 :   if (enabled_features.threads) {
    1157             :     // Shared property of descriptor
    1158             :     Local<String> shared_key = v8_str(isolate, "shared");
    1159             :     v8::MaybeLocal<v8::Value> maybe_value =
    1160         297 :         descriptor->Get(context, shared_key);
    1161             :     v8::Local<v8::Value> value;
    1162         297 :     if (maybe_value.ToLocal(&value)) {
    1163         297 :       is_shared_memory = value->BooleanValue(isolate);
    1164             :     }
    1165             :     // Throw TypeError if shared is true, and the descriptor has no "maximum"
    1166         297 :     if (is_shared_memory && maximum == -1) {
    1167             :       thrower.TypeError(
    1168           8 :           "If shared is true, maximum property should be defined.");
    1169             :       return;
    1170             :     }
    1171             :   }
    1172             : 
    1173             :   i::Handle<i::JSObject> memory_obj;
    1174        8742 :   if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
    1175             :                                 static_cast<uint32_t>(maximum),
    1176        4371 :                                 is_shared_memory)
    1177             :            .ToHandle(&memory_obj)) {
    1178           8 :     thrower.RangeError("could not allocate memory");
    1179           8 :     return;
    1180             :   }
    1181        4363 :   if (is_shared_memory) {
    1182             :     i::Handle<i::JSArrayBuffer> buffer(
    1183             :         i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(),
    1184             :         i_isolate);
    1185             :     Maybe<bool> result =
    1186         249 :         buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    1187         249 :     if (!result.FromJust()) {
    1188             :       thrower.TypeError(
    1189           0 :           "Status of setting SetIntegrityLevel of buffer is false.");
    1190             :       return;
    1191             :     }
    1192             :   }
    1193             :   args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
    1194             : }
    1195             : 
    1196        7560 : void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1197             :   v8::Isolate* isolate = args.GetIsolate();
    1198             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1199       14864 :   HandleScope scope(isolate);
    1200        7304 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
    1201        7560 :   if (!args.IsConstructCall()) {
    1202           8 :     thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
    1203           8 :     return;
    1204             :   }
    1205        7552 :   if (!args[0]->IsObject()) {
    1206         104 :     thrower.TypeError("Argument 0 must be a global descriptor");
    1207         104 :     return;
    1208             :   }
    1209        7448 :   Local<Context> context = isolate->GetCurrentContext();
    1210             :   Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
    1211             : 
    1212             :   // The descriptor's 'mutable'.
    1213             :   bool is_mutable = false;
    1214             :   {
    1215             :     Local<String> mutable_key = v8_str(isolate, "mutable");
    1216        7448 :     v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
    1217             :     v8::Local<v8::Value> value;
    1218        7448 :     if (maybe.ToLocal(&value)) {
    1219        7448 :       is_mutable = value->BooleanValue(isolate);
    1220             :     }
    1221             :   }
    1222             : 
    1223             :   // The descriptor's type, called 'value'. It is called 'value' because this
    1224             :   // descriptor is planned to be re-used as the global's type for reflection,
    1225             :   // so calling it 'type' is redundant.
    1226             :   i::wasm::ValueType type;
    1227             :   {
    1228             :     v8::MaybeLocal<v8::Value> maybe =
    1229        7448 :         descriptor->Get(context, v8_str(isolate, "value"));
    1230             :     v8::Local<v8::Value> value;
    1231        7568 :     if (!maybe.ToLocal(&value)) return;
    1232             :     v8::Local<v8::String> string;
    1233       14896 :     if (!value->ToString(context).ToLocal(&string)) return;
    1234             : 
    1235        7448 :     auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1236        7448 :     if (string->StringEquals(v8_str(isolate, "i32"))) {
    1237             :       type = i::wasm::kWasmI32;
    1238        4864 :     } else if (string->StringEquals(v8_str(isolate, "f32"))) {
    1239             :       type = i::wasm::kWasmF32;
    1240        1928 :     } else if (string->StringEquals(v8_str(isolate, "i64"))) {
    1241             :       type = i::wasm::kWasmI64;
    1242        1832 :     } else if (string->StringEquals(v8_str(isolate, "f64"))) {
    1243             :       type = i::wasm::kWasmF64;
    1244         824 :     } else if (enabled_features.anyref &&
    1245         352 :                string->StringEquals(v8_str(isolate, "anyref"))) {
    1246             :       type = i::wasm::kWasmAnyRef;
    1247         344 :     } else if (enabled_features.anyref &&
    1248         112 :                string->StringEquals(v8_str(isolate, "anyfunc"))) {
    1249             :       type = i::wasm::kWasmAnyFunc;
    1250             :     } else {
    1251             :       thrower.TypeError(
    1252             :           "Descriptor property 'value' must be 'i32', 'i64', 'f32', or "
    1253         120 :           "'f64'");
    1254         120 :       return;
    1255             :     }
    1256             :   }
    1257             : 
    1258             :   const uint32_t offset = 0;
    1259             :   i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
    1260             :       i::WasmGlobalObject::New(i_isolate, i::MaybeHandle<i::JSArrayBuffer>(),
    1261             :                                i::MaybeHandle<i::FixedArray>(), type, offset,
    1262        7328 :                                is_mutable);
    1263             : 
    1264             :   i::Handle<i::WasmGlobalObject> global_obj;
    1265        7328 :   if (!maybe_global_obj.ToHandle(&global_obj)) {
    1266           0 :     thrower.RangeError("could not allocate memory");
    1267           0 :     return;
    1268             :   }
    1269             : 
    1270             :   // Convert value to a WebAssembly value, the default value is 0.
    1271             :   Local<v8::Value> value = Local<Value>::Cast(args[1]);
    1272        7328 :   switch (type) {
    1273             :     case i::wasm::kWasmI32: {
    1274             :       int32_t i32_value = 0;
    1275        2584 :       if (!value->IsUndefined()) {
    1276             :         v8::Local<v8::Int32> int32_value;
    1277        4832 :         if (!value->ToInt32(context).ToLocal(&int32_value)) return;
    1278        4832 :         if (!int32_value->Int32Value(context).To(&i32_value)) return;
    1279             :       }
    1280        2584 :       global_obj->SetI32(i32_value);
    1281             :       break;
    1282             :     }
    1283             :     case i::wasm::kWasmI64: {
    1284             :       int64_t i64_value = 0;
    1285          96 :       if (!value->IsUndefined()) {
    1286          48 :         auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1287          48 :         if (!enabled_features.bigint) {
    1288          16 :           thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
    1289          16 :           return;
    1290             :         }
    1291             : 
    1292             :         v8::Local<v8::BigInt> bigint_value;
    1293          64 :         if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
    1294          24 :         i64_value = bigint_value->Int64Value();
    1295             :       }
    1296          72 :       global_obj->SetI64(i64_value);
    1297          72 :       break;
    1298             :     }
    1299             :     case i::wasm::kWasmF32: {
    1300             :       float f32_value = 0;
    1301        2936 :       if (!value->IsUndefined()) {
    1302             :         double f64_value = 0;
    1303             :         v8::Local<v8::Number> number_value;
    1304        5600 :         if (!value->ToNumber(context).ToLocal(&number_value)) return;
    1305        5600 :         if (!number_value->NumberValue(context).To(&f64_value)) return;
    1306        2800 :         f32_value = static_cast<float>(f64_value);
    1307             :       }
    1308        2936 :       global_obj->SetF32(f32_value);
    1309        2936 :       break;
    1310             :     }
    1311             :     case i::wasm::kWasmF64: {
    1312             :       double f64_value = 0;
    1313        1360 :       if (!value->IsUndefined()) {
    1314             :         v8::Local<v8::Number> number_value;
    1315        2448 :         if (!value->ToNumber(context).ToLocal(&number_value)) return;
    1316        2448 :         if (!number_value->NumberValue(context).To(&f64_value)) return;
    1317             :       }
    1318        1360 :       global_obj->SetF64(f64_value);
    1319             :       break;
    1320             :     }
    1321             :     case i::wasm::kWasmAnyRef: {
    1322         240 :       if (args.Length() < 2) {
    1323             :         // When no inital value is provided, we have to use the WebAssembly
    1324             :         // default value 'null', and not the JS default value 'undefined'.
    1325          48 :         global_obj->SetAnyRef(i_isolate->factory()->null_value());
    1326          48 :         break;
    1327             :       }
    1328         192 :       global_obj->SetAnyRef(Utils::OpenHandle(*value));
    1329         192 :       break;
    1330             :     }
    1331             :     case i::wasm::kWasmAnyFunc: {
    1332         112 :       if (args.Length() < 2) {
    1333             :         // When no inital value is provided, we have to use the WebAssembly
    1334             :         // default value 'null', and not the JS default value 'undefined'.
    1335          32 :         global_obj->SetAnyFunc(i_isolate, i_isolate->factory()->null_value());
    1336          32 :         break;
    1337             :       }
    1338             : 
    1339          80 :       if (!global_obj->SetAnyFunc(i_isolate, Utils::OpenHandle(*value))) {
    1340             :         thrower.TypeError(
    1341             :             "The value of anyfunc globals must be null or an "
    1342          16 :             "exported function");
    1343             :       }
    1344             :       break;
    1345             :     }
    1346             :     default:
    1347           0 :       UNREACHABLE();
    1348             :   }
    1349             : 
    1350             :   i::Handle<i::JSObject> global_js_object(global_obj);
    1351             :   args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
    1352             : }
    1353             : 
    1354             : // WebAssembly.Exception
    1355           8 : void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1356             :   v8::Isolate* isolate = args.GetIsolate();
    1357             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1358          16 :   HandleScope scope(isolate);
    1359           8 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
    1360           8 :   thrower.TypeError("WebAssembly.Exception cannot be called");
    1361           8 : }
    1362             : 
    1363             : constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
    1364             : constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
    1365             : constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
    1366             : constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
    1367             : 
    1368             : #define EXTRACT_THIS(var, WasmType)                                  \
    1369             :   i::Handle<i::WasmType> var;                                        \
    1370             :   {                                                                  \
    1371             :     i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
    1372             :     if (!this_arg->Is##WasmType()) {                                 \
    1373             :       thrower.TypeError("Receiver is not a %s", kName_##WasmType);   \
    1374             :       return;                                                        \
    1375             :     }                                                                \
    1376             :     var = i::Handle<i::WasmType>::cast(this_arg);                    \
    1377             :   }
    1378             : 
    1379    43212953 : void WebAssemblyInstanceGetExports(
    1380             :   const v8::FunctionCallbackInfo<v8::Value>& args) {
    1381             :   v8::Isolate* isolate = args.GetIsolate();
    1382             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1383    86425818 :   HandleScope scope(isolate);
    1384    43212864 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
    1385    43212953 :   EXTRACT_THIS(receiver, WasmInstanceObject);
    1386             :   i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
    1387             :   args.GetReturnValue().Set(Utils::ToLocal(exports_object));
    1388             : }
    1389             : 
    1390        8000 : void WebAssemblyTableGetLength(
    1391             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1392             :   v8::Isolate* isolate = args.GetIsolate();
    1393             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1394       15888 :   HandleScope scope(isolate);
    1395        7888 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
    1396        8000 :   EXTRACT_THIS(receiver, WasmTableObject);
    1397        7888 :   args.GetReturnValue().Set(
    1398             :       v8::Number::New(isolate, receiver->current_length()));
    1399             : }
    1400             : 
    1401             : // WebAssembly.Table.grow(num) -> num
    1402         744 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1403             :   v8::Isolate* isolate = args.GetIsolate();
    1404             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1405        1176 :   HandleScope scope(isolate);
    1406         432 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
    1407         744 :   Local<Context> context = isolate->GetCurrentContext();
    1408         744 :   EXTRACT_THIS(receiver, WasmTableObject);
    1409             : 
    1410             :   uint32_t grow_by;
    1411         648 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) {
    1412             :     return;
    1413             :   }
    1414             : 
    1415             :   i::Handle<i::FixedArray> old_array(receiver->elements(), i_isolate);
    1416         496 :   uint32_t old_size = static_cast<uint32_t>(old_array->length());
    1417             : 
    1418             :   uint64_t max_size64 = receiver->maximum_length().IsUndefined(i_isolate)
    1419             :                             ? i::FLAG_wasm_max_table_size
    1420         936 :                             : receiver->maximum_length()->Number();
    1421         496 :   if (max_size64 > i::FLAG_wasm_max_table_size) {
    1422             :     max_size64 = i::FLAG_wasm_max_table_size;
    1423             :   }
    1424             : 
    1425             :   DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    1426             : 
    1427             :   uint64_t new_size64 =
    1428         496 :       static_cast<uint64_t>(old_size) + static_cast<uint64_t>(grow_by);
    1429         496 :   if (new_size64 > max_size64) {
    1430          64 :     thrower.RangeError("maximum table size exceeded");
    1431          64 :     return;
    1432             :   }
    1433         432 :   uint32_t new_size = static_cast<uint32_t>(new_size64);
    1434             : 
    1435         432 :   if (new_size != old_size) {
    1436         400 :     receiver->Grow(i_isolate, new_size - old_size);
    1437             : 
    1438             :     i::Handle<i::FixedArray> new_array =
    1439         400 :         i_isolate->factory()->NewFixedArray(new_size);
    1440     9597312 :     for (uint32_t i = 0; i < old_size; ++i) {
    1441     9596912 :       new_array->set(i, old_array->get(i));
    1442             :     }
    1443         400 :     i::Object null = i::ReadOnlyRoots(i_isolate).null_value();
    1444   170590448 :     for (uint32_t i = old_size; i < new_size; ++i) new_array->set(i, null);
    1445         400 :     receiver->set_elements(*new_array);
    1446             :   }
    1447             : 
    1448             :   // TODO(gdeepti): use weak links for instances
    1449             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1450             :   return_value.Set(old_size);
    1451             : }
    1452             : 
    1453             : // WebAssembly.Table.get(num) -> JSFunction
    1454       10656 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1455             :   v8::Isolate* isolate = args.GetIsolate();
    1456             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1457       20296 :   HandleScope scope(isolate);
    1458        9640 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
    1459       10656 :   Local<Context> context = isolate->GetCurrentContext();
    1460       10656 :   EXTRACT_THIS(receiver, WasmTableObject);
    1461             : 
    1462             :   uint32_t index;
    1463       10560 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    1464             :     return;
    1465             :   }
    1466       10088 :   if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) {
    1467         448 :     thrower.RangeError("invalid index %u into function table", index);
    1468         448 :     return;
    1469             :   }
    1470             : 
    1471             :   i::Handle<i::Object> result =
    1472        9640 :       i::WasmTableObject::Get(i_isolate, receiver, index);
    1473             : 
    1474             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1475             :   return_value.Set(Utils::ToLocal(result));
    1476             : }
    1477             : 
    1478             : // WebAssembly.Table.set(num, JSFunction)
    1479        4000 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1480             :   v8::Isolate* isolate = args.GetIsolate();
    1481             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1482        7088 :   HandleScope scope(isolate);
    1483        3088 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
    1484        4000 :   Local<Context> context = isolate->GetCurrentContext();
    1485        4000 :   EXTRACT_THIS(table_object, WasmTableObject);
    1486             : 
    1487             :   // Parameter 0.
    1488             :   uint32_t index;
    1489        3896 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    1490             :     return;
    1491             :   }
    1492        3664 :   if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) {
    1493         328 :     thrower.RangeError("invalid index %u into function table", index);
    1494         328 :     return;
    1495             :   }
    1496             : 
    1497        3336 :   i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
    1498        3336 :   if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) {
    1499         248 :     thrower.TypeError("Argument 1 must be null or a WebAssembly function");
    1500         248 :     return;
    1501             :   }
    1502        3088 :   i::WasmTableObject::Set(i_isolate, table_object, index, element);
    1503             : }
    1504             : 
    1505             : // WebAssembly.Table.type(WebAssembly.Table) -> TableType
    1506          96 : void WebAssemblyTableGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1507             :   v8::Isolate* isolate = args.GetIsolate();
    1508         160 :   HandleScope scope(isolate);
    1509             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1510          64 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()");
    1511             : 
    1512          96 :   auto maybe_table = GetFirstArgumentAsTable(args, &thrower);
    1513         128 :   if (thrower.error()) return;
    1514             :   i::Handle<i::WasmTableObject> table = maybe_table.ToHandleChecked();
    1515          64 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1516             : 
    1517             :   Local<String> element;
    1518          64 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    1519          64 :   if (table->type() == i::wasm::ValueType::kWasmAnyFunc) {
    1520             :     element = v8_str(isolate, "anyfunc");
    1521          16 :   } else if (enabled_features.anyref &&
    1522             :              table->type() == i::wasm::ValueType::kWasmAnyRef) {
    1523             :     element = v8_str(isolate, "anyref");
    1524             :   } else {
    1525           0 :     UNREACHABLE();
    1526             :   }
    1527             :   // TODO(aseemgarg): update anyfunc to funcref
    1528         192 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1529         128 :                                v8_str(isolate, "element"), element)
    1530             :            .IsJust()) {
    1531             :     return;
    1532             :   }
    1533             : 
    1534             :   uint32_t curr_size = table->current_length();
    1535             :   DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
    1536         192 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1537             :                                v8_str(isolate, "minimum"),
    1538             :                                v8::Integer::NewFromUnsigned(
    1539         192 :                                    isolate, static_cast<uint32_t>(curr_size)))
    1540             :            .IsJust()) {
    1541             :     return;
    1542             :   }
    1543             : 
    1544          64 :   if (!table->maximum_length()->IsUndefined()) {
    1545          32 :     uint64_t max_size = table->maximum_length()->Number();
    1546             :     DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
    1547          96 :     if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1548             :                                  v8_str(isolate, "maximum"),
    1549             :                                  v8::Integer::NewFromUnsigned(
    1550          96 :                                      isolate, static_cast<uint32_t>(max_size)))
    1551             :              .IsJust()) {
    1552             :       return;
    1553             :     }
    1554             :   }
    1555             : 
    1556             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1557             :   return_value.Set(ret);
    1558             : }
    1559             : 
    1560             : // WebAssembly.Memory.grow(num) -> num
    1561         724 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1562             :   v8::Isolate* isolate = args.GetIsolate();
    1563             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1564        1160 :   HandleScope scope(isolate);
    1565         436 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
    1566         724 :   Local<Context> context = isolate->GetCurrentContext();
    1567         724 :   EXTRACT_THIS(receiver, WasmMemoryObject);
    1568             : 
    1569             :   uint32_t delta_size;
    1570         636 :   if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_size)) {
    1571             :     return;
    1572             :   }
    1573             : 
    1574         516 :   uint64_t max_size64 = receiver->maximum_pages();
    1575         516 :   if (max_size64 > uint64_t{i::wasm::max_mem_pages()}) {
    1576         168 :     max_size64 = i::wasm::max_mem_pages();
    1577             :   }
    1578             :   i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);
    1579             : 
    1580             :   DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    1581             : 
    1582         516 :   uint64_t old_size64 = old_buffer->byte_length() / i::wasm::kWasmPageSize;
    1583         516 :   uint64_t new_size64 = old_size64 + static_cast<uint64_t>(delta_size);
    1584             : 
    1585         516 :   if (new_size64 > max_size64) {
    1586          72 :     thrower.RangeError("Maximum memory size exceeded");
    1587          72 :     return;
    1588             :   }
    1589             : 
    1590         444 :   int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_size);
    1591         444 :   if (ret == -1) {
    1592           8 :     thrower.RangeError("Unable to grow instance memory.");
    1593           8 :     return;
    1594             :   }
    1595             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1596             :   return_value.Set(ret);
    1597             : }
    1598             : 
    1599             : // WebAssembly.Memory.buffer -> ArrayBuffer
    1600    11098634 : void WebAssemblyMemoryGetBuffer(
    1601             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1602             :   v8::Isolate* isolate = args.GetIsolate();
    1603             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1604    22197156 :   HandleScope scope(isolate);
    1605    11098522 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
    1606    11098634 :   EXTRACT_THIS(receiver, WasmMemoryObject);
    1607             : 
    1608             :   i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
    1609             :   DCHECK(buffer_obj->IsJSArrayBuffer());
    1610             :   i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
    1611             :                                      i_isolate);
    1612    11098522 :   if (buffer->is_shared()) {
    1613             :     // TODO(gdeepti): More needed here for when cached buffer, and current
    1614             :     // buffer are out of sync, handle that here when bounds checks, and Grow
    1615             :     // are handled correctly.
    1616             :     Maybe<bool> result =
    1617    11096258 :         buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    1618    11096258 :     if (!result.FromJust()) {
    1619             :       thrower.TypeError(
    1620           0 :           "Status of setting SetIntegrityLevel of buffer is false.");
    1621             :     }
    1622             :   }
    1623             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1624             :   return_value.Set(Utils::ToLocal(buffer));
    1625             : }
    1626             : 
    1627             : // WebAssembly.Memory.type(WebAssembly.Memory) -> MemoryType
    1628          80 : void WebAssemblyMemoryGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1629             :   v8::Isolate* isolate = args.GetIsolate();
    1630         128 :   HandleScope scope(isolate);
    1631             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1632          48 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()");
    1633             : 
    1634          80 :   auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
    1635         112 :   if (thrower.error()) return;
    1636             :   i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
    1637          48 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1638             :   i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
    1639             : 
    1640          48 :   size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
    1641             :   DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
    1642         144 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1643             :                                v8_str(isolate, "minimum"),
    1644             :                                v8::Integer::NewFromUnsigned(
    1645         144 :                                    isolate, static_cast<uint32_t>(curr_size)))
    1646             :            .IsJust()) {
    1647             :     return;
    1648             :   }
    1649             : 
    1650          48 :   if (memory->has_maximum_pages()) {
    1651          24 :     uint64_t max_size = memory->maximum_pages();
    1652             :     DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
    1653          72 :     if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1654             :                                  v8_str(isolate, "maximum"),
    1655             :                                  v8::Integer::NewFromUnsigned(
    1656          72 :                                      isolate, static_cast<uint32_t>(max_size)))
    1657             :              .IsJust()) {
    1658             :       return;
    1659             :     }
    1660             :   }
    1661             : 
    1662             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1663             :   return_value.Set(ret);
    1664             : }
    1665             : 
    1666        9624 : void WebAssemblyGlobalGetValueCommon(
    1667             :     const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
    1668             :   v8::Isolate* isolate = args.GetIsolate();
    1669             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1670       19088 :   HandleScope scope(isolate);
    1671        9464 :   ScheduledErrorThrower thrower(i_isolate, name);
    1672        9624 :   EXTRACT_THIS(receiver, WasmGlobalObject);
    1673             : 
    1674             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1675             : 
    1676        9464 :   switch (receiver->type()) {
    1677             :     case i::wasm::kWasmI32:
    1678             :       return_value.Set(receiver->GetI32());
    1679             :       break;
    1680             :     case i::wasm::kWasmI64: {
    1681         112 :       auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1682         112 :       if (enabled_features.bigint) {
    1683          72 :         Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
    1684             : 
    1685             :         return_value.Set(value);
    1686             :       } else {
    1687          40 :         thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
    1688             :       }
    1689             :       break;
    1690             :     }
    1691             :     case i::wasm::kWasmF32:
    1692        3288 :       return_value.Set(receiver->GetF32());
    1693             :       break;
    1694             :     case i::wasm::kWasmF64:
    1695             :       return_value.Set(receiver->GetF64());
    1696             :       break;
    1697             :     case i::wasm::kWasmAnyRef:
    1698             :     case i::wasm::kWasmAnyFunc:
    1699             :     case i::wasm::kWasmExceptRef:
    1700        1664 :       return_value.Set(Utils::ToLocal(receiver->GetRef()));
    1701             :       break;
    1702             :     default:
    1703           0 :       UNREACHABLE();
    1704             :   }
    1705             : }
    1706             : 
    1707             : // WebAssembly.Global.valueOf() -> num
    1708        3360 : void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1709        3360 :   return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
    1710             : }
    1711             : 
    1712             : // get WebAssembly.Global.value -> num
    1713        6264 : void WebAssemblyGlobalGetValue(
    1714             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1715        6264 :   return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
    1716             : }
    1717             : 
    1718             : // set WebAssembly.Global.value(num)
    1719        2944 : void WebAssemblyGlobalSetValue(
    1720             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1721             :   v8::Isolate* isolate = args.GetIsolate();
    1722             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1723        5568 :   HandleScope scope(isolate);
    1724        2944 :   Local<Context> context = isolate->GetCurrentContext();
    1725        2624 :   ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
    1726        2944 :   EXTRACT_THIS(receiver, WasmGlobalObject);
    1727             : 
    1728        2872 :   if (!receiver->is_mutable()) {
    1729         216 :     thrower.TypeError("Can't set the value of an immutable global.");
    1730         216 :     return;
    1731             :   }
    1732        2656 :   if (args[0]->IsUndefined()) {
    1733          24 :     thrower.TypeError("Argument 0 is required");
    1734          24 :     return;
    1735             :   }
    1736             : 
    1737        2632 :   switch (receiver->type()) {
    1738             :     case i::wasm::kWasmI32: {
    1739             :       int32_t i32_value = 0;
    1740        2000 :       if (!args[0]->Int32Value(context).To(&i32_value)) return;
    1741        1000 :       receiver->SetI32(i32_value);
    1742             :       break;
    1743             :     }
    1744             :     case i::wasm::kWasmI64: {
    1745          32 :       auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
    1746          32 :       if (enabled_features.bigint) {
    1747             :         v8::Local<v8::BigInt> bigint_value;
    1748          48 :         if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
    1749          32 :         receiver->SetI64(bigint_value->Int64Value());
    1750             :       } else {
    1751           8 :         thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
    1752             :       }
    1753          24 :       break;
    1754             :     }
    1755             :     case i::wasm::kWasmF32: {
    1756             :       double f64_value = 0;
    1757        1936 :       if (!args[0]->NumberValue(context).To(&f64_value)) return;
    1758        1936 :       receiver->SetF32(static_cast<float>(f64_value));
    1759             :       break;
    1760             :     }
    1761             :     case i::wasm::kWasmF64: {
    1762             :       double f64_value = 0;
    1763         880 :       if (!args[0]->NumberValue(context).To(&f64_value)) return;
    1764         440 :       receiver->SetF64(f64_value);
    1765             :       break;
    1766             :     }
    1767             :     case i::wasm::kWasmAnyRef:
    1768             :     case i::wasm::kWasmExceptRef: {
    1769         144 :       receiver->SetAnyRef(Utils::OpenHandle(*args[0]));
    1770         144 :       break;
    1771             :     }
    1772             :     case i::wasm::kWasmAnyFunc: {
    1773          48 :       if (!receiver->SetAnyFunc(i_isolate, Utils::OpenHandle(*args[0]))) {
    1774             :         thrower.TypeError(
    1775             :             "value of an anyfunc reference must be either null or an "
    1776          16 :             "exported function");
    1777             :       }
    1778             :       break;
    1779             :     }
    1780             :     default:
    1781           0 :       UNREACHABLE();
    1782             :   }
    1783             : }
    1784             : 
    1785             : // WebAssembly.Global.type(WebAssembly.Global) -> GlobalType
    1786          88 : void WebAssemblyGlobalGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1787             :   v8::Isolate* isolate = args.GetIsolate();
    1788         144 :   HandleScope scope(isolate);
    1789             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    1790          56 :   ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()");
    1791             : 
    1792          88 :   auto maybe_global = GetFirstArgumentAsGlobal(args, &thrower);
    1793         120 :   if (thrower.error()) return;
    1794             :   i::Handle<i::WasmGlobalObject> global = maybe_global.ToHandleChecked();
    1795          56 :   v8::Local<v8::Object> ret = v8::Object::New(isolate);
    1796             : 
    1797         168 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1798             :                                v8_str(isolate, "mutable"),
    1799         112 :                                v8::Boolean::New(isolate, global->is_mutable()))
    1800             :            .IsJust()) {
    1801             :     return;
    1802             :   }
    1803             : 
    1804             :   Local<String> type;
    1805          56 :   switch (global->type()) {
    1806             :     case i::wasm::kWasmI32: {
    1807             :       type = v8_str(isolate, "i32");
    1808          16 :       break;
    1809             :     }
    1810             :     case i::wasm::kWasmI64: {
    1811             :       type = v8_str(isolate, "i64");
    1812           8 :       break;
    1813             :     }
    1814             :     case i::wasm::kWasmF32: {
    1815             :       type = v8_str(isolate, "f32");
    1816           8 :       break;
    1817             :     }
    1818             :     case i::wasm::kWasmF64: {
    1819             :       type = v8_str(isolate, "f64");
    1820           8 :       break;
    1821             :     }
    1822             :     case i::wasm::kWasmAnyRef: {
    1823             :       type = v8_str(isolate, "anyref");
    1824          16 :       break;
    1825             :     }
    1826             :     default:
    1827           0 :       UNREACHABLE();
    1828             :   }
    1829         168 :   if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
    1830         112 :                                v8_str(isolate, "value"), type)
    1831             :            .IsJust()) {
    1832             :     return;
    1833             :   }
    1834             : 
    1835             :   v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
    1836             :   return_value.Set(ret);
    1837             : }
    1838             : 
    1839             : }  // namespace
    1840             : 
    1841             : // TODO(titzer): we use the API to create the function template because the
    1842             : // internal guts are too ugly to replicate here.
    1843     1716652 : static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
    1844             :     i::Isolate* i_isolate, FunctionCallback func) {
    1845             :   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
    1846     1716652 :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
    1847     1716656 :   templ->ReadOnlyPrototype();
    1848     1716655 :   return v8::Utils::OpenHandle(*templ);
    1849             : }
    1850             : 
    1851             : static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
    1852             :     i::Isolate* i_isolate) {
    1853             :   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
    1854      408866 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1855             :   return v8::Utils::OpenHandle(*templ);
    1856             : }
    1857             : 
    1858             : namespace internal {
    1859             : 
    1860     1716654 : Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
    1861             :                               FunctionCallback func) {
    1862     1716654 :   Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
    1863             :   Handle<JSFunction> function =
    1864     3433296 :       ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
    1865             :   DCHECK(function->shared()->HasSharedName());
    1866     1716644 :   return function;
    1867             : }
    1868             : 
    1869     1308045 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
    1870             :                                const char* str, FunctionCallback func,
    1871             :                                int length = 0,
    1872             :                                PropertyAttributes attributes = NONE) {
    1873             :   Handle<String> name = v8_str(isolate, str);
    1874     1308041 :   Handle<JSFunction> function = CreateFunc(isolate, name, func);
    1875             :   function->shared()->set_length(length);
    1876     1308041 :   JSObject::AddProperty(isolate, object, name, function, attributes);
    1877     1308043 :   return function;
    1878             : }
    1879             : 
    1880           0 : Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
    1881             :                                          Handle<JSObject> object,
    1882             :                                          const char* str,
    1883             :                                          FunctionCallback func) {
    1884      408862 :   return InstallFunc(isolate, object, str, func, 1, DONT_ENUM);
    1885             : }
    1886             : 
    1887      326888 : Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
    1888      653778 :   return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
    1889      326890 :       .ToHandleChecked();
    1890             : }
    1891             : 
    1892      245167 : void InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str,
    1893             :                    FunctionCallback func) {
    1894             :   Handle<String> name = v8_str(isolate, str);
    1895             :   Handle<JSFunction> function =
    1896      245167 :       CreateFunc(isolate, GetterName(isolate, name), func);
    1897             : 
    1898      245167 :   Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
    1899             :                                               Utils::ToLocal(function),
    1900      245167 :                                               Local<Function>(), v8::None);
    1901      245167 : }
    1902             : 
    1903       81722 : Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
    1904      163445 :   return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
    1905       81723 :       .ToHandleChecked();
    1906             : }
    1907             : 
    1908       81722 : void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
    1909             :                          const char* str, FunctionCallback getter,
    1910             :                          FunctionCallback setter) {
    1911             :   Handle<String> name = v8_str(isolate, str);
    1912             :   Handle<JSFunction> getter_func =
    1913       81722 :       CreateFunc(isolate, GetterName(isolate, name), getter);
    1914             :   Handle<JSFunction> setter_func =
    1915       81723 :       CreateFunc(isolate, SetterName(isolate, name), setter);
    1916             :   setter_func->shared()->set_length(1);
    1917             : 
    1918             :   v8::PropertyAttribute attributes = v8::None;
    1919             : 
    1920       81722 :   Utils::ToLocal(object)->SetAccessorProperty(
    1921             :       Utils::ToLocal(name), Utils::ToLocal(getter_func),
    1922       81723 :       Utils::ToLocal(setter_func), attributes);
    1923       81722 : }
    1924             : 
    1925             : // Assigns a dummy instance template to the given constructor function. Used to
    1926             : // make sure the implicit receivers for the constructors in this file have an
    1927             : // instance type different from the internal one, they allocate the resulting
    1928             : // object explicitly and ignore implicit receiver.
    1929      408866 : void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
    1930             :   Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
    1931      408865 :   FunctionTemplateInfo::SetInstanceTemplate(
    1932             :       isolate, handle(fun->shared()->get_api_func_data(), isolate),
    1933      408867 :       instance_template);
    1934      408865 : }
    1935             : 
    1936             : // static
    1937     1176301 : void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
    1938     1176301 :   Handle<JSGlobalObject> global = isolate->global_object();
    1939             :   Handle<Context> context(global->native_context(), isolate);
    1940             :   // Install the JS API once only.
    1941             :   Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
    1942     1176301 :   if (!prev->IsUndefined(isolate)) {
    1943             :     DCHECK(prev->IsJSFunction());
    1944     1094578 :     return;
    1945             :   }
    1946             : 
    1947             :   Factory* factory = isolate->factory();
    1948             : 
    1949             :   // Setup WebAssembly
    1950             :   Handle<String> name = v8_str(isolate, "WebAssembly");
    1951             :   NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
    1952       81723 :       name, isolate->strict_function_map(), LanguageMode::kStrict);
    1953       81723 :   Handle<JSFunction> cons = factory->NewFunction(args);
    1954      163446 :   JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
    1955             :   Handle<JSObject> webassembly =
    1956       81723 :       factory->NewJSObject(cons, AllocationType::kOld);
    1957             : 
    1958             :   PropertyAttributes ro_attributes =
    1959             :       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
    1960       81723 :   JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
    1961       81723 :                         name, ro_attributes);
    1962       81723 :   InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
    1963       81721 :   InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
    1964       81723 :   InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
    1965             : 
    1966       81723 :   if (FLAG_wasm_test_streaming) {
    1967             :     isolate->set_wasm_streaming_callback(WasmStreamingCallbackForTesting);
    1968             :   }
    1969             : 
    1970       81723 :   if (isolate->wasm_streaming_callback() != nullptr) {
    1971             :     InstallFunc(isolate, webassembly, "compileStreaming",
    1972          96 :                 WebAssemblyCompileStreaming, 1);
    1973             :     InstallFunc(isolate, webassembly, "instantiateStreaming",
    1974          96 :                 WebAssemblyInstantiateStreaming, 1);
    1975             :   }
    1976             : 
    1977             :   // Expose the API on the global object if configured to do so.
    1978       81723 :   if (exposed_on_global_object) {
    1979       81698 :     JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM);
    1980             :   }
    1981             : 
    1982             :   // Setup Module
    1983             :   Handle<JSFunction> module_constructor =
    1984             :       InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule);
    1985       81723 :   context->set_wasm_module_constructor(*module_constructor);
    1986       81723 :   SetDummyInstanceTemplate(isolate, module_constructor);
    1987       81723 :   JSFunction::EnsureHasInitialMap(module_constructor);
    1988             :   Handle<JSObject> module_proto(
    1989      163445 :       JSObject::cast(module_constructor->instance_prototype()), isolate);
    1990             :   i::Handle<i::Map> module_map =
    1991       81722 :       isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
    1992       81723 :   JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
    1993             :   InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
    1994       81722 :               1);
    1995             :   InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
    1996       81722 :               1);
    1997             :   InstallFunc(isolate, module_constructor, "customSections",
    1998       81721 :               WebAssemblyModuleCustomSections, 2);
    1999       81721 :   JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
    2000       81722 :                         v8_str(isolate, "WebAssembly.Module"), ro_attributes);
    2001             : 
    2002             :   // Setup Instance
    2003             :   Handle<JSFunction> instance_constructor = InstallConstructorFunc(
    2004             :       isolate, webassembly, "Instance", WebAssemblyInstance);
    2005       81723 :   context->set_wasm_instance_constructor(*instance_constructor);
    2006       81722 :   SetDummyInstanceTemplate(isolate, instance_constructor);
    2007       81722 :   JSFunction::EnsureHasInitialMap(instance_constructor);
    2008             :   Handle<JSObject> instance_proto(
    2009      163444 :       JSObject::cast(instance_constructor->instance_prototype()), isolate);
    2010             :   i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
    2011       81722 :       i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
    2012       81722 :   JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
    2013             :   InstallGetter(isolate, instance_proto, "exports",
    2014       81722 :                 WebAssemblyInstanceGetExports);
    2015       81722 :   JSObject::AddProperty(isolate, instance_proto,
    2016             :                         factory->to_string_tag_symbol(),
    2017       81722 :                         v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
    2018             : 
    2019             :   // The context is not set up completely yet. That's why we cannot use
    2020             :   // {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
    2021       81722 :   auto enabled_features = i::wasm::WasmFeaturesFromFlags();
    2022             : 
    2023             :   // Setup Table
    2024             :   Handle<JSFunction> table_constructor =
    2025             :       InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable);
    2026       81723 :   context->set_wasm_table_constructor(*table_constructor);
    2027       81723 :   SetDummyInstanceTemplate(isolate, table_constructor);
    2028       81723 :   JSFunction::EnsureHasInitialMap(table_constructor);
    2029             :   Handle<JSObject> table_proto(
    2030      163445 :       JSObject::cast(table_constructor->instance_prototype()), isolate);
    2031             :   i::Handle<i::Map> table_map =
    2032       81722 :       isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
    2033       81723 :   JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
    2034       81723 :   InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
    2035       81722 :   InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
    2036       81721 :   InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
    2037       81722 :   InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
    2038       81720 :   if (enabled_features.type_reflection) {
    2039          16 :     InstallFunc(isolate, table_constructor, "type", WebAssemblyTableGetType, 1);
    2040             :   }
    2041       81721 :   JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
    2042       81722 :                         v8_str(isolate, "WebAssembly.Table"), ro_attributes);
    2043             : 
    2044             :   // Setup Memory
    2045             :   Handle<JSFunction> memory_constructor =
    2046             :       InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory);
    2047       81723 :   context->set_wasm_memory_constructor(*memory_constructor);
    2048       81723 :   SetDummyInstanceTemplate(isolate, memory_constructor);
    2049       81723 :   JSFunction::EnsureHasInitialMap(memory_constructor);
    2050             :   Handle<JSObject> memory_proto(
    2051      163446 :       JSObject::cast(memory_constructor->instance_prototype()), isolate);
    2052             :   i::Handle<i::Map> memory_map =
    2053       81723 :       isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
    2054       81723 :   JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
    2055       81723 :   InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
    2056       81723 :   InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
    2057       81723 :   if (enabled_features.type_reflection) {
    2058             :     InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryGetType,
    2059          16 :                 1);
    2060             :   }
    2061       81723 :   JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
    2062       81723 :                         v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
    2063             : 
    2064             :   // Setup Global
    2065             :   Handle<JSFunction> global_constructor =
    2066             :       InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal);
    2067       81723 :   context->set_wasm_global_constructor(*global_constructor);
    2068       81723 :   SetDummyInstanceTemplate(isolate, global_constructor);
    2069       81723 :   JSFunction::EnsureHasInitialMap(global_constructor);
    2070             :   Handle<JSObject> global_proto(
    2071      163446 :       JSObject::cast(global_constructor->instance_prototype()), isolate);
    2072             :   i::Handle<i::Map> global_map =
    2073       81723 :       isolate->factory()->NewMap(i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
    2074       81723 :   JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
    2075       81723 :   InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
    2076             :   InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
    2077       81722 :                       WebAssemblyGlobalSetValue);
    2078       81722 :   if (enabled_features.type_reflection) {
    2079             :     InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalGetType,
    2080          16 :                 1);
    2081             :   }
    2082       81723 :   JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
    2083       81723 :                         v8_str(isolate, "WebAssembly.Global"), ro_attributes);
    2084             : 
    2085             :   // Setup Exception
    2086       81723 :   if (enabled_features.eh) {
    2087             :     Handle<JSFunction> exception_constructor = InstallConstructorFunc(
    2088             :         isolate, webassembly, "Exception", WebAssemblyException);
    2089         252 :     context->set_wasm_exception_constructor(*exception_constructor);
    2090         252 :     SetDummyInstanceTemplate(isolate, exception_constructor);
    2091         252 :     JSFunction::EnsureHasInitialMap(exception_constructor);
    2092             :     Handle<JSObject> exception_proto(
    2093         504 :         JSObject::cast(exception_constructor->instance_prototype()), isolate);
    2094             :     i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
    2095         252 :         i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
    2096         252 :     JSFunction::SetInitialMap(exception_constructor, exception_map,
    2097         252 :                               exception_proto);
    2098             :   }
    2099             : 
    2100             :   // Setup errors
    2101             :   Handle<JSFunction> compile_error(
    2102      245169 :       isolate->native_context()->wasm_compile_error_function(), isolate);
    2103       81722 :   JSObject::AddProperty(isolate, webassembly,
    2104             :                         isolate->factory()->CompileError_string(),
    2105       81723 :                         compile_error, DONT_ENUM);
    2106             :   Handle<JSFunction> link_error(
    2107      245166 :       isolate->native_context()->wasm_link_error_function(), isolate);
    2108       81723 :   JSObject::AddProperty(isolate, webassembly,
    2109             :                         isolate->factory()->LinkError_string(), link_error,
    2110       81722 :                         DONT_ENUM);
    2111             :   Handle<JSFunction> runtime_error(
    2112      245169 :       isolate->native_context()->wasm_runtime_error_function(), isolate);
    2113       81723 :   JSObject::AddProperty(isolate, webassembly,
    2114             :                         isolate->factory()->RuntimeError_string(),
    2115       81723 :                         runtime_error, DONT_ENUM);
    2116             : }
    2117             : 
    2118             : #undef ASSIGN
    2119             : #undef EXTRACT_THIS
    2120             : 
    2121             : }  // namespace internal
    2122      122004 : }  // namespace v8

Generated by: LCOV version 1.10