11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/wasm/wasm-js.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <cinttypes> 81cb0ef41Sopenharmony_ci#include <cstring> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "include/v8-function.h" 111cb0ef41Sopenharmony_ci#include "include/v8-wasm.h" 121cb0ef41Sopenharmony_ci#include "src/api/api-inl.h" 131cb0ef41Sopenharmony_ci#include "src/api/api-natives.h" 141cb0ef41Sopenharmony_ci#include "src/ast/ast.h" 151cb0ef41Sopenharmony_ci#include "src/base/logging.h" 161cb0ef41Sopenharmony_ci#include "src/base/overflowing-math.h" 171cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 181cb0ef41Sopenharmony_ci#include "src/common/assert-scope.h" 191cb0ef41Sopenharmony_ci#include "src/execution/execution.h" 201cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h" 211cb0ef41Sopenharmony_ci#include "src/execution/isolate.h" 221cb0ef41Sopenharmony_ci#include "src/handles/global-handles-inl.h" 231cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 241cb0ef41Sopenharmony_ci#include "src/heap/factory.h" 251cb0ef41Sopenharmony_ci#include "src/init/v8.h" 261cb0ef41Sopenharmony_ci#include "src/objects/fixed-array.h" 271cb0ef41Sopenharmony_ci#include "src/objects/instance-type.h" 281cb0ef41Sopenharmony_ci#include "src/objects/js-function.h" 291cb0ef41Sopenharmony_ci#include "src/objects/js-promise-inl.h" 301cb0ef41Sopenharmony_ci#include "src/objects/managed-inl.h" 311cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 321cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h" 331cb0ef41Sopenharmony_ci#include "src/objects/templates.h" 341cb0ef41Sopenharmony_ci#include "src/parsing/parse-info.h" 351cb0ef41Sopenharmony_ci#include "src/tasks/task-utils.h" 361cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h" 371cb0ef41Sopenharmony_ci#include "src/wasm/function-compiler.h" 381cb0ef41Sopenharmony_ci#include "src/wasm/streaming-decoder.h" 391cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 401cb0ef41Sopenharmony_ci#include "src/wasm/wasm-debug.h" 411cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h" 421cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h" 431cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h" 441cb0ef41Sopenharmony_ci#include "src/wasm/wasm-serialization.h" 451cb0ef41Sopenharmony_ci#include "src/wasm/wasm-value.h" 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ciusing v8::internal::wasm::ErrorThrower; 481cb0ef41Sopenharmony_ciusing v8::internal::wasm::ScheduledErrorThrower; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cinamespace v8 { 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciclass WasmStreaming::WasmStreamingImpl { 531cb0ef41Sopenharmony_ci public: 541cb0ef41Sopenharmony_ci WasmStreamingImpl( 551cb0ef41Sopenharmony_ci Isolate* isolate, const char* api_method_name, 561cb0ef41Sopenharmony_ci std::shared_ptr<internal::wasm::CompilationResultResolver> resolver) 571cb0ef41Sopenharmony_ci : isolate_(isolate), resolver_(std::move(resolver)) { 581cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_); 591cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 601cb0ef41Sopenharmony_ci streaming_decoder_ = i::wasm::GetWasmEngine()->StartStreamingCompilation( 611cb0ef41Sopenharmony_ci i_isolate, enabled_features, handle(i_isolate->context(), i_isolate), 621cb0ef41Sopenharmony_ci api_method_name, resolver_); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci void OnBytesReceived(const uint8_t* bytes, size_t size) { 661cb0ef41Sopenharmony_ci streaming_decoder_->OnBytesReceived(base::VectorOf(bytes, size)); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci void Finish(bool can_use_compiled_module) { 691cb0ef41Sopenharmony_ci streaming_decoder_->Finish(can_use_compiled_module); 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci void Abort(MaybeLocal<Value> exception) { 731cb0ef41Sopenharmony_ci i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_)); 741cb0ef41Sopenharmony_ci streaming_decoder_->Abort(); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // If no exception value is provided, we do not reject the promise. This can 771cb0ef41Sopenharmony_ci // happen when streaming compilation gets aborted when no script execution 781cb0ef41Sopenharmony_ci // is allowed anymore, e.g. when a browser tab gets refreshed. 791cb0ef41Sopenharmony_ci if (exception.IsEmpty()) return; 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci resolver_->OnCompilationFailed( 821cb0ef41Sopenharmony_ci Utils::OpenHandle(*exception.ToLocalChecked())); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size) { 861cb0ef41Sopenharmony_ci if (!i::wasm::IsSupportedVersion({bytes, size})) return false; 871cb0ef41Sopenharmony_ci return streaming_decoder_->SetCompiledModuleBytes({bytes, size}); 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci void SetClient(std::shared_ptr<Client> client) { 911cb0ef41Sopenharmony_ci streaming_decoder_->SetModuleCompiledCallback( 921cb0ef41Sopenharmony_ci [client, streaming_decoder = streaming_decoder_]( 931cb0ef41Sopenharmony_ci const std::shared_ptr<i::wasm::NativeModule>& native_module) { 941cb0ef41Sopenharmony_ci base::Vector<const char> url = streaming_decoder->url(); 951cb0ef41Sopenharmony_ci auto compiled_wasm_module = 961cb0ef41Sopenharmony_ci CompiledWasmModule(native_module, url.begin(), url.size()); 971cb0ef41Sopenharmony_ci client->OnModuleCompiled(compiled_wasm_module); 981cb0ef41Sopenharmony_ci }); 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci void SetUrl(base::Vector<const char> url) { streaming_decoder_->SetUrl(url); } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci private: 1041cb0ef41Sopenharmony_ci Isolate* const isolate_; 1051cb0ef41Sopenharmony_ci std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_; 1061cb0ef41Sopenharmony_ci std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_; 1071cb0ef41Sopenharmony_ci}; 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciWasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl) 1101cb0ef41Sopenharmony_ci : impl_(std::move(impl)) { 1111cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.InitializeStreaming"); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci// The destructor is defined here because we have a unique_ptr with forward 1151cb0ef41Sopenharmony_ci// declaration. 1161cb0ef41Sopenharmony_ciWasmStreaming::~WasmStreaming() = default; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_civoid WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) { 1191cb0ef41Sopenharmony_ci TRACE_EVENT1("v8.wasm", "wasm.OnBytesReceived", "bytes", size); 1201cb0ef41Sopenharmony_ci impl_->OnBytesReceived(bytes, size); 1211cb0ef41Sopenharmony_ci} 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_civoid WasmStreaming::Finish(bool can_use_compiled_module) { 1241cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.FinishStreaming"); 1251cb0ef41Sopenharmony_ci impl_->Finish(can_use_compiled_module); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_civoid WasmStreaming::Abort(MaybeLocal<Value> exception) { 1291cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.AbortStreaming"); 1301cb0ef41Sopenharmony_ci impl_->Abort(exception); 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_cibool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) { 1341cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.SetCompiledModuleBytes"); 1351cb0ef41Sopenharmony_ci return impl_->SetCompiledModuleBytes(bytes, size); 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_civoid WasmStreaming::SetClient(std::shared_ptr<Client> client) { 1391cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.WasmStreaming.SetClient"); 1401cb0ef41Sopenharmony_ci impl_->SetClient(client); 1411cb0ef41Sopenharmony_ci} 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_civoid WasmStreaming::SetUrl(const char* url, size_t length) { 1441cb0ef41Sopenharmony_ci DCHECK_EQ('\0', url[length]); // {url} is null-terminated. 1451cb0ef41Sopenharmony_ci TRACE_EVENT1("v8.wasm", "wasm.SetUrl", "url", url); 1461cb0ef41Sopenharmony_ci impl_->SetUrl(base::VectorOf(url, length)); 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci// static 1501cb0ef41Sopenharmony_cistd::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate, 1511cb0ef41Sopenharmony_ci Local<Value> value) { 1521cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.WasmStreaming.Unpack"); 1531cb0ef41Sopenharmony_ci i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate)); 1541cb0ef41Sopenharmony_ci auto managed = 1551cb0ef41Sopenharmony_ci i::Handle<i::Managed<WasmStreaming>>::cast(Utils::OpenHandle(*value)); 1561cb0ef41Sopenharmony_ci return managed->get(); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_cinamespace { 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci#define ASSIGN(type, var, expr) \ 1621cb0ef41Sopenharmony_ci Local<type> var; \ 1631cb0ef41Sopenharmony_ci do { \ 1641cb0ef41Sopenharmony_ci if (!expr.ToLocal(&var)) { \ 1651cb0ef41Sopenharmony_ci DCHECK(i_isolate->has_scheduled_exception()); \ 1661cb0ef41Sopenharmony_ci return; \ 1671cb0ef41Sopenharmony_ci } else { \ 1681cb0ef41Sopenharmony_ci DCHECK(!i_isolate->has_scheduled_exception()); \ 1691cb0ef41Sopenharmony_ci } \ 1701cb0ef41Sopenharmony_ci } while (false) 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_cii::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { 1731cb0ef41Sopenharmony_ci return isolate->factory()->NewStringFromAsciiChecked(str); 1741cb0ef41Sopenharmony_ci} 1751cb0ef41Sopenharmony_ciLocal<String> v8_str(Isolate* isolate, const char* str) { 1761cb0ef41Sopenharmony_ci return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci#define GET_FIRST_ARGUMENT_AS(Type) \ 1801cb0ef41Sopenharmony_ci i::MaybeHandle<i::Wasm##Type##Object> GetFirstArgumentAs##Type( \ 1811cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args, \ 1821cb0ef41Sopenharmony_ci ErrorThrower* thrower) { \ 1831cb0ef41Sopenharmony_ci i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); \ 1841cb0ef41Sopenharmony_ci if (!arg0->IsWasm##Type##Object()) { \ 1851cb0ef41Sopenharmony_ci thrower->TypeError("Argument 0 must be a WebAssembly." #Type); \ 1861cb0ef41Sopenharmony_ci return {}; \ 1871cb0ef41Sopenharmony_ci } \ 1881cb0ef41Sopenharmony_ci return i::Handle<i::Wasm##Type##Object>::cast(arg0); \ 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ciGET_FIRST_ARGUMENT_AS(Module) 1921cb0ef41Sopenharmony_ciGET_FIRST_ARGUMENT_AS(Tag) 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci#undef GET_FIRST_ARGUMENT_AS 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cii::wasm::ModuleWireBytes GetFirstArgumentAsBytes( 1971cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower, 1981cb0ef41Sopenharmony_ci bool* is_shared) { 1991cb0ef41Sopenharmony_ci const uint8_t* start = nullptr; 2001cb0ef41Sopenharmony_ci size_t length = 0; 2011cb0ef41Sopenharmony_ci v8::Local<v8::Value> source = args[0]; 2021cb0ef41Sopenharmony_ci if (source->IsArrayBuffer()) { 2031cb0ef41Sopenharmony_ci // A raw array buffer was passed. 2041cb0ef41Sopenharmony_ci Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source); 2051cb0ef41Sopenharmony_ci auto backing_store = buffer->GetBackingStore(); 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci start = reinterpret_cast<const uint8_t*>(backing_store->Data()); 2081cb0ef41Sopenharmony_ci length = backing_store->ByteLength(); 2091cb0ef41Sopenharmony_ci *is_shared = buffer->IsSharedArrayBuffer(); 2101cb0ef41Sopenharmony_ci } else if (source->IsTypedArray()) { 2111cb0ef41Sopenharmony_ci // A TypedArray was passed. 2121cb0ef41Sopenharmony_ci Local<TypedArray> array = Local<TypedArray>::Cast(source); 2131cb0ef41Sopenharmony_ci Local<ArrayBuffer> buffer = array->Buffer(); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci auto backing_store = buffer->GetBackingStore(); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci start = reinterpret_cast<const uint8_t*>(backing_store->Data()) + 2181cb0ef41Sopenharmony_ci array->ByteOffset(); 2191cb0ef41Sopenharmony_ci length = array->ByteLength(); 2201cb0ef41Sopenharmony_ci *is_shared = buffer->IsSharedArrayBuffer(); 2211cb0ef41Sopenharmony_ci } else { 2221cb0ef41Sopenharmony_ci thrower->TypeError("Argument 0 must be a buffer source"); 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci DCHECK_IMPLIES(length, start != nullptr); 2251cb0ef41Sopenharmony_ci if (length == 0) { 2261cb0ef41Sopenharmony_ci thrower->CompileError("BufferSource argument is empty"); 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci size_t max_length = i::wasm::max_module_size(); 2291cb0ef41Sopenharmony_ci if (length > max_length) { 2301cb0ef41Sopenharmony_ci thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)", 2311cb0ef41Sopenharmony_ci max_length, length); 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr); 2341cb0ef41Sopenharmony_ci return i::wasm::ModuleWireBytes(start, start + length); 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_cii::MaybeHandle<i::JSFunction> GetFirstArgumentAsJSFunction( 2381cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { 2391cb0ef41Sopenharmony_ci i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); 2401cb0ef41Sopenharmony_ci if (!arg0->IsJSFunction()) { 2411cb0ef41Sopenharmony_ci thrower->TypeError("Argument 0 must be a function"); 2421cb0ef41Sopenharmony_ci return {}; 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci return i::Handle<i::JSFunction>::cast(arg0); 2451cb0ef41Sopenharmony_ci} 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_cii::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg, 2481cb0ef41Sopenharmony_ci ErrorThrower* thrower) { 2491cb0ef41Sopenharmony_ci if (arg->IsUndefined()) return {}; 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci if (!arg->IsObject()) { 2521cb0ef41Sopenharmony_ci thrower->TypeError("Argument 1 must be an object"); 2531cb0ef41Sopenharmony_ci return {}; 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci Local<Object> obj = Local<Object>::Cast(arg); 2561cb0ef41Sopenharmony_ci return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); 2571cb0ef41Sopenharmony_ci} 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_cinamespace { 2601cb0ef41Sopenharmony_ci// This class resolves the result of WebAssembly.compile. It just places the 2611cb0ef41Sopenharmony_ci// compilation result in the supplied {promise}. 2621cb0ef41Sopenharmony_ciclass AsyncCompilationResolver : public i::wasm::CompilationResultResolver { 2631cb0ef41Sopenharmony_ci public: 2641cb0ef41Sopenharmony_ci AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise) 2651cb0ef41Sopenharmony_ci : promise_(isolate->global_handles()->Create(*promise)) { 2661cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer(promise_.location(), 2671cb0ef41Sopenharmony_ci kGlobalPromiseHandle); 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci ~AsyncCompilationResolver() override { 2711cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(promise_.location()); 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override { 2751cb0ef41Sopenharmony_ci if (finished_) return; 2761cb0ef41Sopenharmony_ci finished_ = true; 2771cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 2781cb0ef41Sopenharmony_ci i::JSPromise::Resolve(promise_, result); 2791cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), 2801cb0ef41Sopenharmony_ci promise_->GetIsolate()->has_pending_exception()); 2811cb0ef41Sopenharmony_ci } 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci void OnCompilationFailed(i::Handle<i::Object> error_reason) override { 2841cb0ef41Sopenharmony_ci if (finished_) return; 2851cb0ef41Sopenharmony_ci finished_ = true; 2861cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 2871cb0ef41Sopenharmony_ci i::JSPromise::Reject(promise_, error_reason); 2881cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), 2891cb0ef41Sopenharmony_ci promise_->GetIsolate()->has_pending_exception()); 2901cb0ef41Sopenharmony_ci } 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci private: 2931cb0ef41Sopenharmony_ci static constexpr char kGlobalPromiseHandle[] = 2941cb0ef41Sopenharmony_ci "AsyncCompilationResolver::promise_"; 2951cb0ef41Sopenharmony_ci bool finished_ = false; 2961cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise_; 2971cb0ef41Sopenharmony_ci}; 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ciconstexpr char AsyncCompilationResolver::kGlobalPromiseHandle[]; 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci// This class resolves the result of WebAssembly.instantiate(module, imports). 3021cb0ef41Sopenharmony_ci// It just places the instantiation result in the supplied {promise}. 3031cb0ef41Sopenharmony_ciclass InstantiateModuleResultResolver 3041cb0ef41Sopenharmony_ci : public i::wasm::InstantiationResultResolver { 3051cb0ef41Sopenharmony_ci public: 3061cb0ef41Sopenharmony_ci InstantiateModuleResultResolver(i::Isolate* isolate, 3071cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise) 3081cb0ef41Sopenharmony_ci : promise_(isolate->global_handles()->Create(*promise)) { 3091cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer(promise_.location(), 3101cb0ef41Sopenharmony_ci kGlobalPromiseHandle); 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci ~InstantiateModuleResultResolver() override { 3141cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(promise_.location()); 3151cb0ef41Sopenharmony_ci } 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci void OnInstantiationSucceeded( 3181cb0ef41Sopenharmony_ci i::Handle<i::WasmInstanceObject> instance) override { 3191cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 3201cb0ef41Sopenharmony_ci i::JSPromise::Resolve(promise_, instance); 3211cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), 3221cb0ef41Sopenharmony_ci promise_->GetIsolate()->has_pending_exception()); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci void OnInstantiationFailed(i::Handle<i::Object> error_reason) override { 3261cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 3271cb0ef41Sopenharmony_ci i::JSPromise::Reject(promise_, error_reason); 3281cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), 3291cb0ef41Sopenharmony_ci promise_->GetIsolate()->has_pending_exception()); 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci private: 3331cb0ef41Sopenharmony_ci static constexpr char kGlobalPromiseHandle[] = 3341cb0ef41Sopenharmony_ci "InstantiateModuleResultResolver::promise_"; 3351cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise_; 3361cb0ef41Sopenharmony_ci}; 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ciconstexpr char InstantiateModuleResultResolver::kGlobalPromiseHandle[]; 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci// This class resolves the result of WebAssembly.instantiate(bytes, imports). 3411cb0ef41Sopenharmony_ci// For that it creates a new {JSObject} which contains both the provided 3421cb0ef41Sopenharmony_ci// {WasmModuleObject} and the resulting {WebAssemblyInstanceObject} itself. 3431cb0ef41Sopenharmony_ciclass InstantiateBytesResultResolver 3441cb0ef41Sopenharmony_ci : public i::wasm::InstantiationResultResolver { 3451cb0ef41Sopenharmony_ci public: 3461cb0ef41Sopenharmony_ci InstantiateBytesResultResolver(i::Isolate* isolate, 3471cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise, 3481cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject> module) 3491cb0ef41Sopenharmony_ci : isolate_(isolate), 3501cb0ef41Sopenharmony_ci promise_(isolate_->global_handles()->Create(*promise)), 3511cb0ef41Sopenharmony_ci module_(isolate_->global_handles()->Create(*module)) { 3521cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer(promise_.location(), 3531cb0ef41Sopenharmony_ci kGlobalPromiseHandle); 3541cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer(module_.location(), 3551cb0ef41Sopenharmony_ci kGlobalModuleHandle); 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci ~InstantiateBytesResultResolver() override { 3591cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(promise_.location()); 3601cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(module_.location()); 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci void OnInstantiationSucceeded( 3641cb0ef41Sopenharmony_ci i::Handle<i::WasmInstanceObject> instance) override { 3651cb0ef41Sopenharmony_ci // The result is a JSObject with 2 fields which contain the 3661cb0ef41Sopenharmony_ci // WasmInstanceObject and the WasmModuleObject. 3671cb0ef41Sopenharmony_ci i::Handle<i::JSObject> result = 3681cb0ef41Sopenharmony_ci isolate_->factory()->NewJSObject(isolate_->object_function()); 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci i::Handle<i::String> instance_name = 3711cb0ef41Sopenharmony_ci isolate_->factory()->NewStringFromStaticChars("instance"); 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci i::Handle<i::String> module_name = 3741cb0ef41Sopenharmony_ci isolate_->factory()->NewStringFromStaticChars("module"); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci i::JSObject::AddProperty(isolate_, result, instance_name, instance, 3771cb0ef41Sopenharmony_ci i::NONE); 3781cb0ef41Sopenharmony_ci i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE); 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 3811cb0ef41Sopenharmony_ci i::JSPromise::Resolve(promise_, result); 3821cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception()); 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci void OnInstantiationFailed(i::Handle<i::Object> error_reason) override { 3861cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 3871cb0ef41Sopenharmony_ci i::JSPromise::Reject(promise_, error_reason); 3881cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception()); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci private: 3921cb0ef41Sopenharmony_ci static constexpr char kGlobalPromiseHandle[] = 3931cb0ef41Sopenharmony_ci "InstantiateBytesResultResolver::promise_"; 3941cb0ef41Sopenharmony_ci static constexpr char kGlobalModuleHandle[] = 3951cb0ef41Sopenharmony_ci "InstantiateBytesResultResolver::module_"; 3961cb0ef41Sopenharmony_ci i::Isolate* isolate_; 3971cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise_; 3981cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject> module_; 3991cb0ef41Sopenharmony_ci}; 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ciconstexpr char InstantiateBytesResultResolver::kGlobalPromiseHandle[]; 4021cb0ef41Sopenharmony_ciconstexpr char InstantiateBytesResultResolver::kGlobalModuleHandle[]; 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci// This class is the {CompilationResultResolver} for 4051cb0ef41Sopenharmony_ci// WebAssembly.instantiate(bytes, imports). When compilation finishes, 4061cb0ef41Sopenharmony_ci// {AsyncInstantiate} is started on the compilation result. 4071cb0ef41Sopenharmony_ciclass AsyncInstantiateCompileResultResolver 4081cb0ef41Sopenharmony_ci : public i::wasm::CompilationResultResolver { 4091cb0ef41Sopenharmony_ci public: 4101cb0ef41Sopenharmony_ci AsyncInstantiateCompileResultResolver( 4111cb0ef41Sopenharmony_ci i::Isolate* isolate, i::Handle<i::JSPromise> promise, 4121cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSReceiver> maybe_imports) 4131cb0ef41Sopenharmony_ci : isolate_(isolate), 4141cb0ef41Sopenharmony_ci promise_(isolate_->global_handles()->Create(*promise)), 4151cb0ef41Sopenharmony_ci maybe_imports_(maybe_imports.is_null() 4161cb0ef41Sopenharmony_ci ? maybe_imports 4171cb0ef41Sopenharmony_ci : isolate_->global_handles()->Create( 4181cb0ef41Sopenharmony_ci *maybe_imports.ToHandleChecked())) { 4191cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer(promise_.location(), 4201cb0ef41Sopenharmony_ci kGlobalPromiseHandle); 4211cb0ef41Sopenharmony_ci if (!maybe_imports_.is_null()) { 4221cb0ef41Sopenharmony_ci i::GlobalHandles::AnnotateStrongRetainer( 4231cb0ef41Sopenharmony_ci maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle); 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci ~AsyncInstantiateCompileResultResolver() override { 4281cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(promise_.location()); 4291cb0ef41Sopenharmony_ci if (!maybe_imports_.is_null()) { 4301cb0ef41Sopenharmony_ci i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location()); 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override { 4351cb0ef41Sopenharmony_ci if (finished_) return; 4361cb0ef41Sopenharmony_ci finished_ = true; 4371cb0ef41Sopenharmony_ci i::wasm::GetWasmEngine()->AsyncInstantiate( 4381cb0ef41Sopenharmony_ci isolate_, 4391cb0ef41Sopenharmony_ci std::make_unique<InstantiateBytesResultResolver>(isolate_, promise_, 4401cb0ef41Sopenharmony_ci result), 4411cb0ef41Sopenharmony_ci result, maybe_imports_); 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci void OnCompilationFailed(i::Handle<i::Object> error_reason) override { 4451cb0ef41Sopenharmony_ci if (finished_) return; 4461cb0ef41Sopenharmony_ci finished_ = true; 4471cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> promise_result = 4481cb0ef41Sopenharmony_ci i::JSPromise::Reject(promise_, error_reason); 4491cb0ef41Sopenharmony_ci CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception()); 4501cb0ef41Sopenharmony_ci } 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci private: 4531cb0ef41Sopenharmony_ci static constexpr char kGlobalPromiseHandle[] = 4541cb0ef41Sopenharmony_ci "AsyncInstantiateCompileResultResolver::promise_"; 4551cb0ef41Sopenharmony_ci static constexpr char kGlobalImportsHandle[] = 4561cb0ef41Sopenharmony_ci "AsyncInstantiateCompileResultResolver::module_"; 4571cb0ef41Sopenharmony_ci bool finished_ = false; 4581cb0ef41Sopenharmony_ci i::Isolate* isolate_; 4591cb0ef41Sopenharmony_ci i::Handle<i::JSPromise> promise_; 4601cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSReceiver> maybe_imports_; 4611cb0ef41Sopenharmony_ci}; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ciconstexpr char AsyncInstantiateCompileResultResolver::kGlobalPromiseHandle[]; 4641cb0ef41Sopenharmony_ciconstexpr char AsyncInstantiateCompileResultResolver::kGlobalImportsHandle[]; 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_cistd::string ToString(const char* name) { return std::string(name); } 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_cistd::string ToString(const i::Handle<i::String> name) { 4691cb0ef41Sopenharmony_ci return std::string("Property '") + name->ToCString().get() + "'"; 4701cb0ef41Sopenharmony_ci} 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci// Web IDL: '[EnforceRange] unsigned long' 4731cb0ef41Sopenharmony_ci// Previously called ToNonWrappingUint32 in the draft WebAssembly JS spec. 4741cb0ef41Sopenharmony_ci// https://heycam.github.io/webidl/#EnforceRange 4751cb0ef41Sopenharmony_citemplate <typename T> 4761cb0ef41Sopenharmony_cibool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context, 4771cb0ef41Sopenharmony_ci ErrorThrower* thrower, uint32_t* res) { 4781cb0ef41Sopenharmony_ci double double_number; 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci if (!v->NumberValue(context).To(&double_number)) { 4811cb0ef41Sopenharmony_ci thrower->TypeError("%s must be convertible to a number", 4821cb0ef41Sopenharmony_ci ToString(argument_name).c_str()); 4831cb0ef41Sopenharmony_ci return false; 4841cb0ef41Sopenharmony_ci } 4851cb0ef41Sopenharmony_ci if (!std::isfinite(double_number)) { 4861cb0ef41Sopenharmony_ci thrower->TypeError("%s must be convertible to a valid number", 4871cb0ef41Sopenharmony_ci ToString(argument_name).c_str()); 4881cb0ef41Sopenharmony_ci return false; 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci if (double_number < 0) { 4911cb0ef41Sopenharmony_ci thrower->TypeError("%s must be non-negative", 4921cb0ef41Sopenharmony_ci ToString(argument_name).c_str()); 4931cb0ef41Sopenharmony_ci return false; 4941cb0ef41Sopenharmony_ci } 4951cb0ef41Sopenharmony_ci if (double_number > std::numeric_limits<uint32_t>::max()) { 4961cb0ef41Sopenharmony_ci thrower->TypeError("%s must be in the unsigned long range", 4971cb0ef41Sopenharmony_ci ToString(argument_name).c_str()); 4981cb0ef41Sopenharmony_ci return false; 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci *res = static_cast<uint32_t>(double_number); 5021cb0ef41Sopenharmony_ci return true; 5031cb0ef41Sopenharmony_ci} 5041cb0ef41Sopenharmony_ci} // namespace 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci// WebAssembly.compile(bytes) -> Promise 5071cb0ef41Sopenharmony_civoid WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { 5081cb0ef41Sopenharmony_ci constexpr const char* kAPIMethodName = "WebAssembly.compile()"; 5091cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 5101cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci HandleScope scope(isolate); 5131cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_ci if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) { 5161cb0ef41Sopenharmony_ci thrower.CompileError("Wasm code generation disallowed by embedder"); 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 5201cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context)); 5211cb0ef41Sopenharmony_ci Local<Promise> promise = promise_resolver->GetPromise(); 5221cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 5231cb0ef41Sopenharmony_ci return_value.Set(promise); 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci std::shared_ptr<i::wasm::CompilationResultResolver> resolver( 5261cb0ef41Sopenharmony_ci new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise))); 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci bool is_shared = false; 5291cb0ef41Sopenharmony_ci auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared); 5301cb0ef41Sopenharmony_ci if (thrower.error()) { 5311cb0ef41Sopenharmony_ci resolver->OnCompilationFailed(thrower.Reify()); 5321cb0ef41Sopenharmony_ci return; 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci // Asynchronous compilation handles copying wire bytes if necessary. 5351cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 5361cb0ef41Sopenharmony_ci i::wasm::GetWasmEngine()->AsyncCompile(i_isolate, enabled_features, 5371cb0ef41Sopenharmony_ci std::move(resolver), bytes, is_shared, 5381cb0ef41Sopenharmony_ci kAPIMethodName); 5391cb0ef41Sopenharmony_ci} 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_civoid WasmStreamingCallbackForTesting( 5421cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 5431cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 5441cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci HandleScope scope(isolate); 5471cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()"); 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_ci std::shared_ptr<v8::WasmStreaming> streaming = 5501cb0ef41Sopenharmony_ci v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data()); 5511cb0ef41Sopenharmony_ci 5521cb0ef41Sopenharmony_ci bool is_shared = false; 5531cb0ef41Sopenharmony_ci i::wasm::ModuleWireBytes bytes = 5541cb0ef41Sopenharmony_ci GetFirstArgumentAsBytes(args, &thrower, &is_shared); 5551cb0ef41Sopenharmony_ci if (thrower.error()) { 5561cb0ef41Sopenharmony_ci streaming->Abort(Utils::ToLocal(thrower.Reify())); 5571cb0ef41Sopenharmony_ci return; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci streaming->OnBytesReceived(bytes.start(), bytes.length()); 5601cb0ef41Sopenharmony_ci streaming->Finish(); 5611cb0ef41Sopenharmony_ci CHECK(!thrower.error()); 5621cb0ef41Sopenharmony_ci} 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_civoid WasmStreamingPromiseFailedCallback( 5651cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 5661cb0ef41Sopenharmony_ci std::shared_ptr<v8::WasmStreaming> streaming = 5671cb0ef41Sopenharmony_ci v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data()); 5681cb0ef41Sopenharmony_ci streaming->Abort(args[0]); 5691cb0ef41Sopenharmony_ci} 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_ci// WebAssembly.compileStreaming(Response | Promise<Response>) 5721cb0ef41Sopenharmony_ci// -> Promise<WebAssembly.Module> 5731cb0ef41Sopenharmony_civoid WebAssemblyCompileStreaming( 5741cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 5751cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 5761cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5771cb0ef41Sopenharmony_ci HandleScope scope(isolate); 5781cb0ef41Sopenharmony_ci const char* const kAPIMethodName = "WebAssembly.compileStreaming()"; 5791cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); 5801cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci // Create and assign the return value of this function. 5831cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context)); 5841cb0ef41Sopenharmony_ci Local<Promise> promise = result_resolver->GetPromise(); 5851cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 5861cb0ef41Sopenharmony_ci return_value.Set(promise); 5871cb0ef41Sopenharmony_ci 5881cb0ef41Sopenharmony_ci // Prepare the CompilationResultResolver for the compilation. 5891cb0ef41Sopenharmony_ci auto resolver = std::make_shared<AsyncCompilationResolver>( 5901cb0ef41Sopenharmony_ci i_isolate, Utils::OpenHandle(*promise)); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) { 5931cb0ef41Sopenharmony_ci thrower.CompileError("Wasm code generation disallowed by embedder"); 5941cb0ef41Sopenharmony_ci resolver->OnCompilationFailed(thrower.Reify()); 5951cb0ef41Sopenharmony_ci return; 5961cb0ef41Sopenharmony_ci } 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci // Allocate the streaming decoder in a Managed so we can pass it to the 5991cb0ef41Sopenharmony_ci // embedder. 6001cb0ef41Sopenharmony_ci i::Handle<i::Managed<WasmStreaming>> data = 6011cb0ef41Sopenharmony_ci i::Managed<WasmStreaming>::Allocate( 6021cb0ef41Sopenharmony_ci i_isolate, 0, 6031cb0ef41Sopenharmony_ci std::make_unique<WasmStreaming::WasmStreamingImpl>( 6041cb0ef41Sopenharmony_ci isolate, kAPIMethodName, resolver)); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback()); 6071cb0ef41Sopenharmony_ci ASSIGN( 6081cb0ef41Sopenharmony_ci v8::Function, compile_callback, 6091cb0ef41Sopenharmony_ci v8::Function::New(context, i_isolate->wasm_streaming_callback(), 6101cb0ef41Sopenharmony_ci Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1)); 6111cb0ef41Sopenharmony_ci ASSIGN( 6121cb0ef41Sopenharmony_ci v8::Function, reject_callback, 6131cb0ef41Sopenharmony_ci v8::Function::New(context, WasmStreamingPromiseFailedCallback, 6141cb0ef41Sopenharmony_ci Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1)); 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci // The parameter may be of type {Response} or of type {Promise<Response>}. 6171cb0ef41Sopenharmony_ci // Treat either case of parameter as Promise.resolve(parameter) 6181cb0ef41Sopenharmony_ci // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_ci // Ending with: 6211cb0ef41Sopenharmony_ci // return Promise.resolve(parameter).then(compile_callback); 6221cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context)); 6231cb0ef41Sopenharmony_ci if (!input_resolver->Resolve(context, args[0]).IsJust()) return; 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci // We do not have any use of the result here. The {compile_callback} will 6261cb0ef41Sopenharmony_ci // start streaming compilation, which will eventually resolve the promise we 6271cb0ef41Sopenharmony_ci // set as result value. 6281cb0ef41Sopenharmony_ci USE(input_resolver->GetPromise()->Then(context, compile_callback, 6291cb0ef41Sopenharmony_ci reject_callback)); 6301cb0ef41Sopenharmony_ci} 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci// WebAssembly.validate(bytes) -> bool 6331cb0ef41Sopenharmony_civoid WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) { 6341cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 6351cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6361cb0ef41Sopenharmony_ci HandleScope scope(isolate); 6371cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()"); 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci bool is_shared = false; 6401cb0ef41Sopenharmony_ci auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared); 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci if (thrower.error()) { 6451cb0ef41Sopenharmony_ci if (thrower.wasm_error()) thrower.Reset(); // Clear error. 6461cb0ef41Sopenharmony_ci return_value.Set(v8::False(isolate)); 6471cb0ef41Sopenharmony_ci return; 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 6511cb0ef41Sopenharmony_ci bool validated = false; 6521cb0ef41Sopenharmony_ci if (is_shared) { 6531cb0ef41Sopenharmony_ci // Make a copy of the wire bytes to avoid concurrent modification. 6541cb0ef41Sopenharmony_ci std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]); 6551cb0ef41Sopenharmony_ci memcpy(copy.get(), bytes.start(), bytes.length()); 6561cb0ef41Sopenharmony_ci i::wasm::ModuleWireBytes bytes_copy(copy.get(), 6571cb0ef41Sopenharmony_ci copy.get() + bytes.length()); 6581cb0ef41Sopenharmony_ci validated = i::wasm::GetWasmEngine()->SyncValidate( 6591cb0ef41Sopenharmony_ci i_isolate, enabled_features, bytes_copy); 6601cb0ef41Sopenharmony_ci } else { 6611cb0ef41Sopenharmony_ci // The wire bytes are not shared, OK to use them directly. 6621cb0ef41Sopenharmony_ci validated = i::wasm::GetWasmEngine()->SyncValidate(i_isolate, 6631cb0ef41Sopenharmony_ci enabled_features, bytes); 6641cb0ef41Sopenharmony_ci } 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci return_value.Set(Boolean::New(isolate, validated)); 6671cb0ef41Sopenharmony_ci} 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_cinamespace { 6701cb0ef41Sopenharmony_cibool TransferPrototype(i::Isolate* isolate, i::Handle<i::JSObject> destination, 6711cb0ef41Sopenharmony_ci i::Handle<i::JSReceiver> source) { 6721cb0ef41Sopenharmony_ci i::MaybeHandle<i::HeapObject> maybe_prototype = 6731cb0ef41Sopenharmony_ci i::JSObject::GetPrototype(isolate, source); 6741cb0ef41Sopenharmony_ci i::Handle<i::HeapObject> prototype; 6751cb0ef41Sopenharmony_ci if (maybe_prototype.ToHandle(&prototype)) { 6761cb0ef41Sopenharmony_ci Maybe<bool> result = i::JSObject::SetPrototype( 6771cb0ef41Sopenharmony_ci isolate, destination, prototype, 6781cb0ef41Sopenharmony_ci /*from_javascript=*/false, internal::kThrowOnError); 6791cb0ef41Sopenharmony_ci if (!result.FromJust()) { 6801cb0ef41Sopenharmony_ci DCHECK(isolate->has_pending_exception()); 6811cb0ef41Sopenharmony_ci return false; 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci } 6841cb0ef41Sopenharmony_ci return true; 6851cb0ef41Sopenharmony_ci} 6861cb0ef41Sopenharmony_ci} // namespace 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_ci// new WebAssembly.Module(bytes) -> WebAssembly.Module 6891cb0ef41Sopenharmony_civoid WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { 6901cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 6911cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6921cb0ef41Sopenharmony_ci if (i_isolate->wasm_module_callback()(args)) return; 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_ci HandleScope scope(isolate); 6951cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()"); 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 6981cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Module must be invoked with 'new'"); 6991cb0ef41Sopenharmony_ci return; 7001cb0ef41Sopenharmony_ci } 7011cb0ef41Sopenharmony_ci if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) { 7021cb0ef41Sopenharmony_ci thrower.CompileError("Wasm code generation disallowed by embedder"); 7031cb0ef41Sopenharmony_ci return; 7041cb0ef41Sopenharmony_ci } 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci bool is_shared = false; 7071cb0ef41Sopenharmony_ci auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared); 7081cb0ef41Sopenharmony_ci 7091cb0ef41Sopenharmony_ci if (thrower.error()) { 7101cb0ef41Sopenharmony_ci return; 7111cb0ef41Sopenharmony_ci } 7121cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 7131cb0ef41Sopenharmony_ci i::MaybeHandle<i::WasmModuleObject> maybe_module_obj; 7141cb0ef41Sopenharmony_ci if (is_shared) { 7151cb0ef41Sopenharmony_ci // Make a copy of the wire bytes to avoid concurrent modification. 7161cb0ef41Sopenharmony_ci std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]); 7171cb0ef41Sopenharmony_ci memcpy(copy.get(), bytes.start(), bytes.length()); 7181cb0ef41Sopenharmony_ci i::wasm::ModuleWireBytes bytes_copy(copy.get(), 7191cb0ef41Sopenharmony_ci copy.get() + bytes.length()); 7201cb0ef41Sopenharmony_ci maybe_module_obj = i::wasm::GetWasmEngine()->SyncCompile( 7211cb0ef41Sopenharmony_ci i_isolate, enabled_features, &thrower, bytes_copy); 7221cb0ef41Sopenharmony_ci } else { 7231cb0ef41Sopenharmony_ci // The wire bytes are not shared, OK to use them directly. 7241cb0ef41Sopenharmony_ci maybe_module_obj = i::wasm::GetWasmEngine()->SyncCompile( 7251cb0ef41Sopenharmony_ci i_isolate, enabled_features, &thrower, bytes); 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject> module_obj; 7291cb0ef41Sopenharmony_ci if (!maybe_module_obj.ToHandle(&module_obj)) return; 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 7321cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 7331cb0ef41Sopenharmony_ci // and use {module_obj} instead, but it does have the correct prototype, 7341cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 7351cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Module} directly, but some 7361cb0ef41Sopenharmony_ci // subclass: {module_obj} has {WebAssembly.Module}'s prototype at this 7371cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 7381cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, module_obj, 7391cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 7401cb0ef41Sopenharmony_ci return; 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 7441cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(i::Handle<i::JSObject>::cast(module_obj))); 7451cb0ef41Sopenharmony_ci} 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ci// WebAssembly.Module.imports(module) -> Array<Import> 7481cb0ef41Sopenharmony_civoid WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { 7491cb0ef41Sopenharmony_ci HandleScope scope(args.GetIsolate()); 7501cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 7511cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 7521cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()"); 7531cb0ef41Sopenharmony_ci 7541cb0ef41Sopenharmony_ci auto maybe_module = GetFirstArgumentAsModule(args, &thrower); 7551cb0ef41Sopenharmony_ci if (thrower.error()) return; 7561cb0ef41Sopenharmony_ci auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked()); 7571cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(imports)); 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci// WebAssembly.Module.exports(module) -> Array<Export> 7611cb0ef41Sopenharmony_civoid WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) { 7621cb0ef41Sopenharmony_ci HandleScope scope(args.GetIsolate()); 7631cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 7641cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 7651cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()"); 7661cb0ef41Sopenharmony_ci 7671cb0ef41Sopenharmony_ci auto maybe_module = GetFirstArgumentAsModule(args, &thrower); 7681cb0ef41Sopenharmony_ci if (thrower.error()) return; 7691cb0ef41Sopenharmony_ci auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked()); 7701cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(exports)); 7711cb0ef41Sopenharmony_ci} 7721cb0ef41Sopenharmony_ci 7731cb0ef41Sopenharmony_ci// WebAssembly.Module.customSections(module, name) -> Array<Section> 7741cb0ef41Sopenharmony_civoid WebAssemblyModuleCustomSections( 7751cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 7761cb0ef41Sopenharmony_ci HandleScope scope(args.GetIsolate()); 7771cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 7781cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 7791cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, 7801cb0ef41Sopenharmony_ci "WebAssembly.Module.customSections()"); 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ci auto maybe_module = GetFirstArgumentAsModule(args, &thrower); 7831cb0ef41Sopenharmony_ci if (thrower.error()) return; 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci if (args[1]->IsUndefined()) { 7861cb0ef41Sopenharmony_ci thrower.TypeError("Argument 1 is required"); 7871cb0ef41Sopenharmony_ci return; 7881cb0ef41Sopenharmony_ci } 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci i::MaybeHandle<i::Object> maybe_name = 7911cb0ef41Sopenharmony_ci i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1])); 7921cb0ef41Sopenharmony_ci i::Handle<i::Object> name; 7931cb0ef41Sopenharmony_ci if (!maybe_name.ToHandle(&name)) return; 7941cb0ef41Sopenharmony_ci auto custom_sections = 7951cb0ef41Sopenharmony_ci i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), 7961cb0ef41Sopenharmony_ci i::Handle<i::String>::cast(name), &thrower); 7971cb0ef41Sopenharmony_ci if (thrower.error()) return; 7981cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); 7991cb0ef41Sopenharmony_ci} 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ci// new WebAssembly.Instance(module, imports) -> WebAssembly.Instance 8021cb0ef41Sopenharmony_civoid WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { 8031cb0ef41Sopenharmony_ci Isolate* isolate = args.GetIsolate(); 8041cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 8051cb0ef41Sopenharmony_ci i_isolate->CountUsage( 8061cb0ef41Sopenharmony_ci v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation); 8071cb0ef41Sopenharmony_ci 8081cb0ef41Sopenharmony_ci HandleScope scope(args.GetIsolate()); 8091cb0ef41Sopenharmony_ci if (i_isolate->wasm_instance_callback()(args)) return; 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSObject> maybe_instance_obj; 8121cb0ef41Sopenharmony_ci { 8131cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); 8141cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 8151cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Instance must be invoked with 'new'"); 8161cb0ef41Sopenharmony_ci return; 8171cb0ef41Sopenharmony_ci } 8181cb0ef41Sopenharmony_ci 8191cb0ef41Sopenharmony_ci i::MaybeHandle<i::WasmModuleObject> maybe_module = 8201cb0ef41Sopenharmony_ci GetFirstArgumentAsModule(args, &thrower); 8211cb0ef41Sopenharmony_ci if (thrower.error()) return; 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject> module_obj = maybe_module.ToHandleChecked(); 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSReceiver> maybe_imports = 8261cb0ef41Sopenharmony_ci GetValueAsImports(args[1], &thrower); 8271cb0ef41Sopenharmony_ci if (thrower.error()) return; 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci maybe_instance_obj = i::wasm::GetWasmEngine()->SyncInstantiate( 8301cb0ef41Sopenharmony_ci i_isolate, &thrower, module_obj, maybe_imports, 8311cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSArrayBuffer>()); 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci i::Handle<i::JSObject> instance_obj; 8351cb0ef41Sopenharmony_ci if (!maybe_instance_obj.ToHandle(&instance_obj)) { 8361cb0ef41Sopenharmony_ci DCHECK(i_isolate->has_scheduled_exception()); 8371cb0ef41Sopenharmony_ci return; 8381cb0ef41Sopenharmony_ci } 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 8411cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 8421cb0ef41Sopenharmony_ci // and use {instance_obj} instead, but it does have the correct prototype, 8431cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 8441cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Instance} directly, but some 8451cb0ef41Sopenharmony_ci // subclass: {instance_obj} has {WebAssembly.Instance}'s prototype at this 8461cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 8471cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, instance_obj, 8481cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 8491cb0ef41Sopenharmony_ci return; 8501cb0ef41Sopenharmony_ci } 8511cb0ef41Sopenharmony_ci 8521cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(instance_obj)); 8531cb0ef41Sopenharmony_ci} 8541cb0ef41Sopenharmony_ci 8551cb0ef41Sopenharmony_ci// WebAssembly.instantiateStreaming(Response | Promise<Response> [, imports]) 8561cb0ef41Sopenharmony_ci// -> Promise<ResultObject> 8571cb0ef41Sopenharmony_ci// (where ResultObject has a "module" and an "instance" field) 8581cb0ef41Sopenharmony_civoid WebAssemblyInstantiateStreaming( 8591cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 8601cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 8611cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 8621cb0ef41Sopenharmony_ci i_isolate->CountUsage( 8631cb0ef41Sopenharmony_ci v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation); 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_ci HandleScope scope(isolate); 8661cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 8671cb0ef41Sopenharmony_ci const char* const kAPIMethodName = "WebAssembly.instantiateStreaming()"; 8681cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); 8691cb0ef41Sopenharmony_ci 8701cb0ef41Sopenharmony_ci // Create and assign the return value of this function. 8711cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context)); 8721cb0ef41Sopenharmony_ci Local<Promise> promise = result_resolver->GetPromise(); 8731cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 8741cb0ef41Sopenharmony_ci return_value.Set(promise); 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci // Create an InstantiateResultResolver in case there is an issue with the 8771cb0ef41Sopenharmony_ci // passed parameters. 8781cb0ef41Sopenharmony_ci std::unique_ptr<i::wasm::InstantiationResultResolver> resolver( 8791cb0ef41Sopenharmony_ci new InstantiateModuleResultResolver(i_isolate, 8801cb0ef41Sopenharmony_ci Utils::OpenHandle(*promise))); 8811cb0ef41Sopenharmony_ci 8821cb0ef41Sopenharmony_ci if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) { 8831cb0ef41Sopenharmony_ci thrower.CompileError("Wasm code generation disallowed by embedder"); 8841cb0ef41Sopenharmony_ci resolver->OnInstantiationFailed(thrower.Reify()); 8851cb0ef41Sopenharmony_ci return; 8861cb0ef41Sopenharmony_ci } 8871cb0ef41Sopenharmony_ci 8881cb0ef41Sopenharmony_ci // If args.Length < 2, this will be undefined - see FunctionCallbackInfo. 8891cb0ef41Sopenharmony_ci Local<Value> ffi = args[1]; 8901cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSReceiver> maybe_imports = 8911cb0ef41Sopenharmony_ci GetValueAsImports(ffi, &thrower); 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci if (thrower.error()) { 8941cb0ef41Sopenharmony_ci resolver->OnInstantiationFailed(thrower.Reify()); 8951cb0ef41Sopenharmony_ci return; 8961cb0ef41Sopenharmony_ci } 8971cb0ef41Sopenharmony_ci 8981cb0ef41Sopenharmony_ci // We start compilation now, we have no use for the 8991cb0ef41Sopenharmony_ci // {InstantiationResultResolver}. 9001cb0ef41Sopenharmony_ci resolver.reset(); 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_ci std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver( 9031cb0ef41Sopenharmony_ci new AsyncInstantiateCompileResultResolver( 9041cb0ef41Sopenharmony_ci i_isolate, Utils::OpenHandle(*promise), maybe_imports)); 9051cb0ef41Sopenharmony_ci 9061cb0ef41Sopenharmony_ci // Allocate the streaming decoder in a Managed so we can pass it to the 9071cb0ef41Sopenharmony_ci // embedder. 9081cb0ef41Sopenharmony_ci i::Handle<i::Managed<WasmStreaming>> data = 9091cb0ef41Sopenharmony_ci i::Managed<WasmStreaming>::Allocate( 9101cb0ef41Sopenharmony_ci i_isolate, 0, 9111cb0ef41Sopenharmony_ci std::make_unique<WasmStreaming::WasmStreamingImpl>( 9121cb0ef41Sopenharmony_ci isolate, kAPIMethodName, compilation_resolver)); 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback()); 9151cb0ef41Sopenharmony_ci ASSIGN( 9161cb0ef41Sopenharmony_ci v8::Function, compile_callback, 9171cb0ef41Sopenharmony_ci v8::Function::New(context, i_isolate->wasm_streaming_callback(), 9181cb0ef41Sopenharmony_ci Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1)); 9191cb0ef41Sopenharmony_ci ASSIGN( 9201cb0ef41Sopenharmony_ci v8::Function, reject_callback, 9211cb0ef41Sopenharmony_ci v8::Function::New(context, WasmStreamingPromiseFailedCallback, 9221cb0ef41Sopenharmony_ci Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1)); 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ci // The parameter may be of type {Response} or of type {Promise<Response>}. 9251cb0ef41Sopenharmony_ci // Treat either case of parameter as Promise.resolve(parameter) 9261cb0ef41Sopenharmony_ci // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci // Ending with: 9291cb0ef41Sopenharmony_ci // return Promise.resolve(parameter).then(compile_callback); 9301cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context)); 9311cb0ef41Sopenharmony_ci if (!input_resolver->Resolve(context, args[0]).IsJust()) return; 9321cb0ef41Sopenharmony_ci 9331cb0ef41Sopenharmony_ci // We do not have any use of the result here. The {compile_callback} will 9341cb0ef41Sopenharmony_ci // start streaming compilation, which will eventually resolve the promise we 9351cb0ef41Sopenharmony_ci // set as result value. 9361cb0ef41Sopenharmony_ci USE(input_resolver->GetPromise()->Then(context, compile_callback, 9371cb0ef41Sopenharmony_ci reject_callback)); 9381cb0ef41Sopenharmony_ci} 9391cb0ef41Sopenharmony_ci 9401cb0ef41Sopenharmony_ci// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance 9411cb0ef41Sopenharmony_ci// WebAssembly.instantiate(bytes, imports) -> 9421cb0ef41Sopenharmony_ci// {module: WebAssembly.Module, instance: WebAssembly.Instance} 9431cb0ef41Sopenharmony_civoid WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { 9441cb0ef41Sopenharmony_ci constexpr const char* kAPIMethodName = "WebAssembly.instantiate()"; 9451cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 9461cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 9471cb0ef41Sopenharmony_ci i_isolate->CountUsage( 9481cb0ef41Sopenharmony_ci v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation); 9491cb0ef41Sopenharmony_ci 9501cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); 9511cb0ef41Sopenharmony_ci 9521cb0ef41Sopenharmony_ci HandleScope scope(isolate); 9531cb0ef41Sopenharmony_ci 9541cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context)); 9571cb0ef41Sopenharmony_ci Local<Promise> promise = promise_resolver->GetPromise(); 9581cb0ef41Sopenharmony_ci args.GetReturnValue().Set(promise); 9591cb0ef41Sopenharmony_ci 9601cb0ef41Sopenharmony_ci std::unique_ptr<i::wasm::InstantiationResultResolver> resolver( 9611cb0ef41Sopenharmony_ci new InstantiateModuleResultResolver(i_isolate, 9621cb0ef41Sopenharmony_ci Utils::OpenHandle(*promise))); 9631cb0ef41Sopenharmony_ci 9641cb0ef41Sopenharmony_ci Local<Value> first_arg_value = args[0]; 9651cb0ef41Sopenharmony_ci i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value); 9661cb0ef41Sopenharmony_ci if (!first_arg->IsJSObject()) { 9671cb0ef41Sopenharmony_ci thrower.TypeError( 9681cb0ef41Sopenharmony_ci "Argument 0 must be a buffer source or a WebAssembly.Module object"); 9691cb0ef41Sopenharmony_ci resolver->OnInstantiationFailed(thrower.Reify()); 9701cb0ef41Sopenharmony_ci return; 9711cb0ef41Sopenharmony_ci } 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci // If args.Length < 2, this will be undefined - see FunctionCallbackInfo. 9741cb0ef41Sopenharmony_ci Local<Value> ffi = args[1]; 9751cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSReceiver> maybe_imports = 9761cb0ef41Sopenharmony_ci GetValueAsImports(ffi, &thrower); 9771cb0ef41Sopenharmony_ci 9781cb0ef41Sopenharmony_ci if (thrower.error()) { 9791cb0ef41Sopenharmony_ci resolver->OnInstantiationFailed(thrower.Reify()); 9801cb0ef41Sopenharmony_ci return; 9811cb0ef41Sopenharmony_ci } 9821cb0ef41Sopenharmony_ci 9831cb0ef41Sopenharmony_ci if (first_arg->IsWasmModuleObject()) { 9841cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject> module_obj = 9851cb0ef41Sopenharmony_ci i::Handle<i::WasmModuleObject>::cast(first_arg); 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci i::wasm::GetWasmEngine()->AsyncInstantiate(i_isolate, std::move(resolver), 9881cb0ef41Sopenharmony_ci module_obj, maybe_imports); 9891cb0ef41Sopenharmony_ci return; 9901cb0ef41Sopenharmony_ci } 9911cb0ef41Sopenharmony_ci 9921cb0ef41Sopenharmony_ci bool is_shared = false; 9931cb0ef41Sopenharmony_ci auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared); 9941cb0ef41Sopenharmony_ci if (thrower.error()) { 9951cb0ef41Sopenharmony_ci resolver->OnInstantiationFailed(thrower.Reify()); 9961cb0ef41Sopenharmony_ci return; 9971cb0ef41Sopenharmony_ci } 9981cb0ef41Sopenharmony_ci 9991cb0ef41Sopenharmony_ci // We start compilation now, we have no use for the 10001cb0ef41Sopenharmony_ci // {InstantiationResultResolver}. 10011cb0ef41Sopenharmony_ci resolver.reset(); 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ci std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver( 10041cb0ef41Sopenharmony_ci new AsyncInstantiateCompileResultResolver( 10051cb0ef41Sopenharmony_ci i_isolate, Utils::OpenHandle(*promise), maybe_imports)); 10061cb0ef41Sopenharmony_ci 10071cb0ef41Sopenharmony_ci // The first parameter is a buffer source, we have to check if we are allowed 10081cb0ef41Sopenharmony_ci // to compile it. 10091cb0ef41Sopenharmony_ci if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) { 10101cb0ef41Sopenharmony_ci thrower.CompileError("Wasm code generation disallowed by embedder"); 10111cb0ef41Sopenharmony_ci compilation_resolver->OnCompilationFailed(thrower.Reify()); 10121cb0ef41Sopenharmony_ci return; 10131cb0ef41Sopenharmony_ci } 10141cb0ef41Sopenharmony_ci 10151cb0ef41Sopenharmony_ci // Asynchronous compilation handles copying wire bytes if necessary. 10161cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 10171cb0ef41Sopenharmony_ci i::wasm::GetWasmEngine()->AsyncCompile(i_isolate, enabled_features, 10181cb0ef41Sopenharmony_ci std::move(compilation_resolver), bytes, 10191cb0ef41Sopenharmony_ci is_shared, kAPIMethodName); 10201cb0ef41Sopenharmony_ci} 10211cb0ef41Sopenharmony_ci 10221cb0ef41Sopenharmony_cibool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, 10231cb0ef41Sopenharmony_ci Local<Context> context, v8::Local<v8::Value> value, 10241cb0ef41Sopenharmony_ci i::Handle<i::String> property_name, int64_t* result, 10251cb0ef41Sopenharmony_ci int64_t lower_bound, uint64_t upper_bound) { 10261cb0ef41Sopenharmony_ci uint32_t number; 10271cb0ef41Sopenharmony_ci if (!EnforceUint32(property_name, value, context, thrower, &number)) { 10281cb0ef41Sopenharmony_ci return false; 10291cb0ef41Sopenharmony_ci } 10301cb0ef41Sopenharmony_ci if (number < lower_bound) { 10311cb0ef41Sopenharmony_ci thrower->RangeError("Property '%s': value %" PRIu32 10321cb0ef41Sopenharmony_ci " is below the lower bound %" PRIx64, 10331cb0ef41Sopenharmony_ci property_name->ToCString().get(), number, lower_bound); 10341cb0ef41Sopenharmony_ci return false; 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci if (number > upper_bound) { 10371cb0ef41Sopenharmony_ci thrower->RangeError("Property '%s': value %" PRIu32 10381cb0ef41Sopenharmony_ci " is above the upper bound %" PRIu64, 10391cb0ef41Sopenharmony_ci property_name->ToCString().get(), number, upper_bound); 10401cb0ef41Sopenharmony_ci return false; 10411cb0ef41Sopenharmony_ci } 10421cb0ef41Sopenharmony_ci 10431cb0ef41Sopenharmony_ci *result = static_cast<int64_t>(number); 10441cb0ef41Sopenharmony_ci return true; 10451cb0ef41Sopenharmony_ci} 10461cb0ef41Sopenharmony_ci 10471cb0ef41Sopenharmony_cibool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, 10481cb0ef41Sopenharmony_ci Local<Context> context, 10491cb0ef41Sopenharmony_ci Local<v8::Object> object, 10501cb0ef41Sopenharmony_ci Local<String> property, bool* has_property, 10511cb0ef41Sopenharmony_ci int64_t* result, int64_t lower_bound, 10521cb0ef41Sopenharmony_ci uint64_t upper_bound) { 10531cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 10541cb0ef41Sopenharmony_ci if (!object->Get(context, property).ToLocal(&value)) { 10551cb0ef41Sopenharmony_ci return false; 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_ci // Web IDL: dictionary presence 10591cb0ef41Sopenharmony_ci // https://heycam.github.io/webidl/#dfn-present 10601cb0ef41Sopenharmony_ci if (value->IsUndefined()) { 10611cb0ef41Sopenharmony_ci if (has_property != nullptr) *has_property = false; 10621cb0ef41Sopenharmony_ci return true; 10631cb0ef41Sopenharmony_ci } 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_ci if (has_property != nullptr) *has_property = true; 10661cb0ef41Sopenharmony_ci i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property); 10671cb0ef41Sopenharmony_ci 10681cb0ef41Sopenharmony_ci return GetIntegerProperty(isolate, thrower, context, value, property_name, 10691cb0ef41Sopenharmony_ci result, lower_bound, upper_bound); 10701cb0ef41Sopenharmony_ci} 10711cb0ef41Sopenharmony_ci 10721cb0ef41Sopenharmony_ci// Fetch 'initial' or 'minimum' property from object. If both are provided, 10731cb0ef41Sopenharmony_ci// a TypeError is thrown. 10741cb0ef41Sopenharmony_ci// TODO(aseemgarg): change behavior when the following bug is resolved: 10751cb0ef41Sopenharmony_ci// https://github.com/WebAssembly/js-types/issues/6 10761cb0ef41Sopenharmony_cibool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower, 10771cb0ef41Sopenharmony_ci Local<Context> context, 10781cb0ef41Sopenharmony_ci Local<v8::Object> object, int64_t* result, 10791cb0ef41Sopenharmony_ci int64_t lower_bound, uint64_t upper_bound) { 10801cb0ef41Sopenharmony_ci bool has_initial = false; 10811cb0ef41Sopenharmony_ci if (!GetOptionalIntegerProperty(isolate, thrower, context, object, 10821cb0ef41Sopenharmony_ci v8_str(isolate, "initial"), &has_initial, 10831cb0ef41Sopenharmony_ci result, lower_bound, upper_bound)) { 10841cb0ef41Sopenharmony_ci return false; 10851cb0ef41Sopenharmony_ci } 10861cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate( 10871cb0ef41Sopenharmony_ci reinterpret_cast<i::Isolate*>(isolate)); 10881cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 10891cb0ef41Sopenharmony_ci bool has_minimum = false; 10901cb0ef41Sopenharmony_ci int64_t minimum = 0; 10911cb0ef41Sopenharmony_ci if (!GetOptionalIntegerProperty(isolate, thrower, context, object, 10921cb0ef41Sopenharmony_ci v8_str(isolate, "minimum"), &has_minimum, 10931cb0ef41Sopenharmony_ci &minimum, lower_bound, upper_bound)) { 10941cb0ef41Sopenharmony_ci return false; 10951cb0ef41Sopenharmony_ci } 10961cb0ef41Sopenharmony_ci if (has_initial && has_minimum) { 10971cb0ef41Sopenharmony_ci thrower->TypeError( 10981cb0ef41Sopenharmony_ci "The properties 'initial' and 'minimum' are not allowed at the same " 10991cb0ef41Sopenharmony_ci "time"); 11001cb0ef41Sopenharmony_ci return false; 11011cb0ef41Sopenharmony_ci } 11021cb0ef41Sopenharmony_ci if (has_minimum) { 11031cb0ef41Sopenharmony_ci // Only {minimum} exists, so we use {minimum} as {initial}. 11041cb0ef41Sopenharmony_ci has_initial = true; 11051cb0ef41Sopenharmony_ci *result = minimum; 11061cb0ef41Sopenharmony_ci } 11071cb0ef41Sopenharmony_ci } 11081cb0ef41Sopenharmony_ci if (!has_initial) { 11091cb0ef41Sopenharmony_ci // TODO(aseemgarg): update error message when the spec issue is resolved. 11101cb0ef41Sopenharmony_ci thrower->TypeError("Property 'initial' is required"); 11111cb0ef41Sopenharmony_ci return false; 11121cb0ef41Sopenharmony_ci } 11131cb0ef41Sopenharmony_ci return true; 11141cb0ef41Sopenharmony_ci} 11151cb0ef41Sopenharmony_ci 11161cb0ef41Sopenharmony_cinamespace { 11171cb0ef41Sopenharmony_cii::Handle<i::Object> DefaultReferenceValue(i::Isolate* isolate, 11181cb0ef41Sopenharmony_ci i::wasm::ValueType type) { 11191cb0ef41Sopenharmony_ci if (type == i::wasm::kWasmFuncRef) { 11201cb0ef41Sopenharmony_ci return isolate->factory()->null_value(); 11211cb0ef41Sopenharmony_ci } 11221cb0ef41Sopenharmony_ci if (type.is_reference()) { 11231cb0ef41Sopenharmony_ci return isolate->factory()->undefined_value(); 11241cb0ef41Sopenharmony_ci } 11251cb0ef41Sopenharmony_ci UNREACHABLE(); 11261cb0ef41Sopenharmony_ci} 11271cb0ef41Sopenharmony_ci} // namespace 11281cb0ef41Sopenharmony_ci 11291cb0ef41Sopenharmony_ci// new WebAssembly.Table(args) -> WebAssembly.Table 11301cb0ef41Sopenharmony_civoid WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { 11311cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 11321cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 11331cb0ef41Sopenharmony_ci HandleScope scope(isolate); 11341cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table()"); 11351cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 11361cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Table must be invoked with 'new'"); 11371cb0ef41Sopenharmony_ci return; 11381cb0ef41Sopenharmony_ci } 11391cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 11401cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a table descriptor"); 11411cb0ef41Sopenharmony_ci return; 11421cb0ef41Sopenharmony_ci } 11431cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 11441cb0ef41Sopenharmony_ci Local<v8::Object> descriptor = Local<Object>::Cast(args[0]); 11451cb0ef41Sopenharmony_ci i::wasm::ValueType type; 11461cb0ef41Sopenharmony_ci // The descriptor's 'element'. 11471cb0ef41Sopenharmony_ci { 11481cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> maybe = 11491cb0ef41Sopenharmony_ci descriptor->Get(context, v8_str(isolate, "element")); 11501cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 11511cb0ef41Sopenharmony_ci if (!maybe.ToLocal(&value)) return; 11521cb0ef41Sopenharmony_ci v8::Local<v8::String> string; 11531cb0ef41Sopenharmony_ci if (!value->ToString(context).ToLocal(&string)) return; 11541cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 11551cb0ef41Sopenharmony_ci // The JS api uses 'anyfunc' instead of 'funcref'. 11561cb0ef41Sopenharmony_ci if (string->StringEquals(v8_str(isolate, "anyfunc"))) { 11571cb0ef41Sopenharmony_ci type = i::wasm::kWasmFuncRef; 11581cb0ef41Sopenharmony_ci } else if (enabled_features.has_type_reflection() && 11591cb0ef41Sopenharmony_ci string->StringEquals(v8_str(isolate, "funcref"))) { 11601cb0ef41Sopenharmony_ci // With the type reflection proposal, "funcref" replaces "anyfunc", 11611cb0ef41Sopenharmony_ci // and anyfunc just becomes an alias for "funcref". 11621cb0ef41Sopenharmony_ci type = i::wasm::kWasmFuncRef; 11631cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "externref"))) { 11641cb0ef41Sopenharmony_ci // externref is known as anyref as of wasm-gc. 11651cb0ef41Sopenharmony_ci type = i::wasm::kWasmAnyRef; 11661cb0ef41Sopenharmony_ci } else { 11671cb0ef41Sopenharmony_ci thrower.TypeError( 11681cb0ef41Sopenharmony_ci "Descriptor property 'element' must be a WebAssembly reference type"); 11691cb0ef41Sopenharmony_ci return; 11701cb0ef41Sopenharmony_ci } 11711cb0ef41Sopenharmony_ci } 11721cb0ef41Sopenharmony_ci 11731cb0ef41Sopenharmony_ci int64_t initial = 0; 11741cb0ef41Sopenharmony_ci if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor, 11751cb0ef41Sopenharmony_ci &initial, 0, 11761cb0ef41Sopenharmony_ci i::wasm::max_table_init_entries())) { 11771cb0ef41Sopenharmony_ci return; 11781cb0ef41Sopenharmony_ci } 11791cb0ef41Sopenharmony_ci // The descriptor's 'maximum'. 11801cb0ef41Sopenharmony_ci int64_t maximum = -1; 11811cb0ef41Sopenharmony_ci bool has_maximum = true; 11821cb0ef41Sopenharmony_ci if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor, 11831cb0ef41Sopenharmony_ci v8_str(isolate, "maximum"), &has_maximum, 11841cb0ef41Sopenharmony_ci &maximum, initial, 11851cb0ef41Sopenharmony_ci std::numeric_limits<uint32_t>::max())) { 11861cb0ef41Sopenharmony_ci return; 11871cb0ef41Sopenharmony_ci } 11881cb0ef41Sopenharmony_ci 11891cb0ef41Sopenharmony_ci i::Handle<i::FixedArray> fixed_array; 11901cb0ef41Sopenharmony_ci i::Handle<i::WasmTableObject> table_obj = 11911cb0ef41Sopenharmony_ci i::WasmTableObject::New(i_isolate, i::Handle<i::WasmInstanceObject>(), 11921cb0ef41Sopenharmony_ci type, static_cast<uint32_t>(initial), has_maximum, 11931cb0ef41Sopenharmony_ci static_cast<uint32_t>(maximum), &fixed_array, 11941cb0ef41Sopenharmony_ci DefaultReferenceValue(i_isolate, type)); 11951cb0ef41Sopenharmony_ci 11961cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 11971cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 11981cb0ef41Sopenharmony_ci // and use {table_obj} instead, but it does have the correct prototype, 11991cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 12001cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Table} directly, but some 12011cb0ef41Sopenharmony_ci // subclass: {table_obj} has {WebAssembly.Table}'s prototype at this 12021cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 12031cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, table_obj, 12041cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 12051cb0ef41Sopenharmony_ci return; 12061cb0ef41Sopenharmony_ci } 12071cb0ef41Sopenharmony_ci 12081cb0ef41Sopenharmony_ci if (initial > 0 && args.Length() >= 2 && !args[1]->IsUndefined()) { 12091cb0ef41Sopenharmony_ci i::Handle<i::Object> element = Utils::OpenHandle(*args[1]); 12101cb0ef41Sopenharmony_ci if (!i::WasmTableObject::IsValidElement(i_isolate, table_obj, element)) { 12111cb0ef41Sopenharmony_ci thrower.TypeError( 12121cb0ef41Sopenharmony_ci "Argument 2 must be undefined, null, or a value of type compatible " 12131cb0ef41Sopenharmony_ci "with the type of the new table."); 12141cb0ef41Sopenharmony_ci return; 12151cb0ef41Sopenharmony_ci } 12161cb0ef41Sopenharmony_ci // TODO(7748): Generalize this if other table types are allowed. 12171cb0ef41Sopenharmony_ci if (type == i::wasm::kWasmFuncRef && !element->IsNull()) { 12181cb0ef41Sopenharmony_ci element = i::WasmInternalFunction::FromExternal(element, i_isolate) 12191cb0ef41Sopenharmony_ci .ToHandleChecked(); 12201cb0ef41Sopenharmony_ci } 12211cb0ef41Sopenharmony_ci for (uint32_t index = 0; index < static_cast<uint32_t>(initial); ++index) { 12221cb0ef41Sopenharmony_ci i::WasmTableObject::Set(i_isolate, table_obj, index, element); 12231cb0ef41Sopenharmony_ci } 12241cb0ef41Sopenharmony_ci } 12251cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 12261cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(i::Handle<i::JSObject>::cast(table_obj))); 12271cb0ef41Sopenharmony_ci} 12281cb0ef41Sopenharmony_ci 12291cb0ef41Sopenharmony_civoid WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { 12301cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 12311cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 12321cb0ef41Sopenharmony_ci HandleScope scope(isolate); 12331cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()"); 12341cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 12351cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Memory must be invoked with 'new'"); 12361cb0ef41Sopenharmony_ci return; 12371cb0ef41Sopenharmony_ci } 12381cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 12391cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a memory descriptor"); 12401cb0ef41Sopenharmony_ci return; 12411cb0ef41Sopenharmony_ci } 12421cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 12431cb0ef41Sopenharmony_ci Local<v8::Object> descriptor = Local<Object>::Cast(args[0]); 12441cb0ef41Sopenharmony_ci 12451cb0ef41Sopenharmony_ci int64_t initial = 0; 12461cb0ef41Sopenharmony_ci if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor, 12471cb0ef41Sopenharmony_ci &initial, 0, i::wasm::kSpecMaxMemoryPages)) { 12481cb0ef41Sopenharmony_ci return; 12491cb0ef41Sopenharmony_ci } 12501cb0ef41Sopenharmony_ci // The descriptor's 'maximum'. 12511cb0ef41Sopenharmony_ci int64_t maximum = i::WasmMemoryObject::kNoMaximum; 12521cb0ef41Sopenharmony_ci if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor, 12531cb0ef41Sopenharmony_ci v8_str(isolate, "maximum"), nullptr, &maximum, 12541cb0ef41Sopenharmony_ci initial, i::wasm::kSpecMaxMemoryPages)) { 12551cb0ef41Sopenharmony_ci return; 12561cb0ef41Sopenharmony_ci } 12571cb0ef41Sopenharmony_ci 12581cb0ef41Sopenharmony_ci auto shared = i::SharedFlag::kNotShared; 12591cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 12601cb0ef41Sopenharmony_ci if (enabled_features.has_threads()) { 12611cb0ef41Sopenharmony_ci // Shared property of descriptor 12621cb0ef41Sopenharmony_ci Local<String> shared_key = v8_str(isolate, "shared"); 12631cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> maybe_value = 12641cb0ef41Sopenharmony_ci descriptor->Get(context, shared_key); 12651cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 12661cb0ef41Sopenharmony_ci if (maybe_value.ToLocal(&value)) { 12671cb0ef41Sopenharmony_ci shared = value->BooleanValue(isolate) ? i::SharedFlag::kShared 12681cb0ef41Sopenharmony_ci : i::SharedFlag::kNotShared; 12691cb0ef41Sopenharmony_ci } else { 12701cb0ef41Sopenharmony_ci DCHECK(i_isolate->has_scheduled_exception()); 12711cb0ef41Sopenharmony_ci return; 12721cb0ef41Sopenharmony_ci } 12731cb0ef41Sopenharmony_ci 12741cb0ef41Sopenharmony_ci // Throw TypeError if shared is true, and the descriptor has no "maximum" 12751cb0ef41Sopenharmony_ci if (shared == i::SharedFlag::kShared && maximum == -1) { 12761cb0ef41Sopenharmony_ci thrower.TypeError( 12771cb0ef41Sopenharmony_ci "If shared is true, maximum property should be defined."); 12781cb0ef41Sopenharmony_ci return; 12791cb0ef41Sopenharmony_ci } 12801cb0ef41Sopenharmony_ci } 12811cb0ef41Sopenharmony_ci 12821cb0ef41Sopenharmony_ci i::Handle<i::JSObject> memory_obj; 12831cb0ef41Sopenharmony_ci if (!i::WasmMemoryObject::New(i_isolate, static_cast<int>(initial), 12841cb0ef41Sopenharmony_ci static_cast<int>(maximum), shared) 12851cb0ef41Sopenharmony_ci .ToHandle(&memory_obj)) { 12861cb0ef41Sopenharmony_ci thrower.RangeError("could not allocate memory"); 12871cb0ef41Sopenharmony_ci return; 12881cb0ef41Sopenharmony_ci } 12891cb0ef41Sopenharmony_ci 12901cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 12911cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 12921cb0ef41Sopenharmony_ci // and use {memory_obj} instead, but it does have the correct prototype, 12931cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 12941cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Memory} directly, but some 12951cb0ef41Sopenharmony_ci // subclass: {memory_obj} has {WebAssembly.Memory}'s prototype at this 12961cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 12971cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, memory_obj, 12981cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 12991cb0ef41Sopenharmony_ci return; 13001cb0ef41Sopenharmony_ci } 13011cb0ef41Sopenharmony_ci 13021cb0ef41Sopenharmony_ci if (shared == i::SharedFlag::kShared) { 13031cb0ef41Sopenharmony_ci i::Handle<i::JSArrayBuffer> buffer( 13041cb0ef41Sopenharmony_ci i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(), 13051cb0ef41Sopenharmony_ci i_isolate); 13061cb0ef41Sopenharmony_ci Maybe<bool> result = 13071cb0ef41Sopenharmony_ci buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow); 13081cb0ef41Sopenharmony_ci if (!result.FromJust()) { 13091cb0ef41Sopenharmony_ci thrower.TypeError( 13101cb0ef41Sopenharmony_ci "Status of setting SetIntegrityLevel of buffer is false."); 13111cb0ef41Sopenharmony_ci return; 13121cb0ef41Sopenharmony_ci } 13131cb0ef41Sopenharmony_ci } 13141cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); 13151cb0ef41Sopenharmony_ci} 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_ci// Determines the type encoded in a value type property (e.g. type reflection). 13181cb0ef41Sopenharmony_ci// Returns false if there was an exception, true upon success. On success the 13191cb0ef41Sopenharmony_ci// outgoing {type} is set accordingly, or set to {wasm::kWasmVoid} in case the 13201cb0ef41Sopenharmony_ci// type could not be properly recognized. 13211cb0ef41Sopenharmony_cibool GetValueType(Isolate* isolate, MaybeLocal<Value> maybe, 13221cb0ef41Sopenharmony_ci Local<Context> context, i::wasm::ValueType* type, 13231cb0ef41Sopenharmony_ci i::wasm::WasmFeatures enabled_features) { 13241cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 13251cb0ef41Sopenharmony_ci if (!maybe.ToLocal(&value)) return false; 13261cb0ef41Sopenharmony_ci v8::Local<v8::String> string; 13271cb0ef41Sopenharmony_ci if (!value->ToString(context).ToLocal(&string)) return false; 13281cb0ef41Sopenharmony_ci if (string->StringEquals(v8_str(isolate, "i32"))) { 13291cb0ef41Sopenharmony_ci *type = i::wasm::kWasmI32; 13301cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "f32"))) { 13311cb0ef41Sopenharmony_ci *type = i::wasm::kWasmF32; 13321cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "i64"))) { 13331cb0ef41Sopenharmony_ci *type = i::wasm::kWasmI64; 13341cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "f64"))) { 13351cb0ef41Sopenharmony_ci *type = i::wasm::kWasmF64; 13361cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "externref"))) { 13371cb0ef41Sopenharmony_ci *type = i::wasm::kWasmAnyRef; 13381cb0ef41Sopenharmony_ci } else if (enabled_features.has_type_reflection() && 13391cb0ef41Sopenharmony_ci string->StringEquals(v8_str(isolate, "funcref"))) { 13401cb0ef41Sopenharmony_ci // The type reflection proposal renames "anyfunc" to "funcref", and makes 13411cb0ef41Sopenharmony_ci // "anyfunc" an alias of "funcref". 13421cb0ef41Sopenharmony_ci *type = i::wasm::kWasmFuncRef; 13431cb0ef41Sopenharmony_ci } else if (string->StringEquals(v8_str(isolate, "anyfunc"))) { 13441cb0ef41Sopenharmony_ci // The JS api spec uses 'anyfunc' instead of 'funcref'. 13451cb0ef41Sopenharmony_ci *type = i::wasm::kWasmFuncRef; 13461cb0ef41Sopenharmony_ci } else if (enabled_features.has_gc() && 13471cb0ef41Sopenharmony_ci string->StringEquals(v8_str(isolate, "eqref"))) { 13481cb0ef41Sopenharmony_ci *type = i::wasm::kWasmEqRef; 13491cb0ef41Sopenharmony_ci } else { 13501cb0ef41Sopenharmony_ci // Unrecognized type. 13511cb0ef41Sopenharmony_ci *type = i::wasm::kWasmVoid; 13521cb0ef41Sopenharmony_ci } 13531cb0ef41Sopenharmony_ci return true; 13541cb0ef41Sopenharmony_ci} 13551cb0ef41Sopenharmony_ci 13561cb0ef41Sopenharmony_cinamespace { 13571cb0ef41Sopenharmony_ci 13581cb0ef41Sopenharmony_cibool ToI32(Local<v8::Value> value, Local<Context> context, int32_t* i32_value) { 13591cb0ef41Sopenharmony_ci if (!value->IsUndefined()) { 13601cb0ef41Sopenharmony_ci v8::Local<v8::Int32> int32_value; 13611cb0ef41Sopenharmony_ci if (!value->ToInt32(context).ToLocal(&int32_value)) return false; 13621cb0ef41Sopenharmony_ci if (!int32_value->Int32Value(context).To(i32_value)) return false; 13631cb0ef41Sopenharmony_ci } 13641cb0ef41Sopenharmony_ci return true; 13651cb0ef41Sopenharmony_ci} 13661cb0ef41Sopenharmony_ci 13671cb0ef41Sopenharmony_cibool ToI64(Local<v8::Value> value, Local<Context> context, int64_t* i64_value) { 13681cb0ef41Sopenharmony_ci if (!value->IsUndefined()) { 13691cb0ef41Sopenharmony_ci v8::Local<v8::BigInt> bigint_value; 13701cb0ef41Sopenharmony_ci if (!value->ToBigInt(context).ToLocal(&bigint_value)) return false; 13711cb0ef41Sopenharmony_ci *i64_value = bigint_value->Int64Value(); 13721cb0ef41Sopenharmony_ci } 13731cb0ef41Sopenharmony_ci return true; 13741cb0ef41Sopenharmony_ci} 13751cb0ef41Sopenharmony_ci 13761cb0ef41Sopenharmony_cibool ToF32(Local<v8::Value> value, Local<Context> context, float* f32_value) { 13771cb0ef41Sopenharmony_ci if (!value->IsUndefined()) { 13781cb0ef41Sopenharmony_ci double f64_value = 0; 13791cb0ef41Sopenharmony_ci v8::Local<v8::Number> number_value; 13801cb0ef41Sopenharmony_ci if (!value->ToNumber(context).ToLocal(&number_value)) return false; 13811cb0ef41Sopenharmony_ci if (!number_value->NumberValue(context).To(&f64_value)) return false; 13821cb0ef41Sopenharmony_ci *f32_value = i::DoubleToFloat32(f64_value); 13831cb0ef41Sopenharmony_ci } 13841cb0ef41Sopenharmony_ci return true; 13851cb0ef41Sopenharmony_ci} 13861cb0ef41Sopenharmony_ci 13871cb0ef41Sopenharmony_cibool ToF64(Local<v8::Value> value, Local<Context> context, double* f64_value) { 13881cb0ef41Sopenharmony_ci if (!value->IsUndefined()) { 13891cb0ef41Sopenharmony_ci v8::Local<v8::Number> number_value; 13901cb0ef41Sopenharmony_ci if (!value->ToNumber(context).ToLocal(&number_value)) return false; 13911cb0ef41Sopenharmony_ci if (!number_value->NumberValue(context).To(f64_value)) return false; 13921cb0ef41Sopenharmony_ci } 13931cb0ef41Sopenharmony_ci return true; 13941cb0ef41Sopenharmony_ci} 13951cb0ef41Sopenharmony_ci 13961cb0ef41Sopenharmony_ci} // namespace 13971cb0ef41Sopenharmony_ci 13981cb0ef41Sopenharmony_ci// WebAssembly.Global 13991cb0ef41Sopenharmony_civoid WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) { 14001cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 14011cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 14021cb0ef41Sopenharmony_ci HandleScope scope(isolate); 14031cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()"); 14041cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 14051cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Global must be invoked with 'new'"); 14061cb0ef41Sopenharmony_ci return; 14071cb0ef41Sopenharmony_ci } 14081cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 14091cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a global descriptor"); 14101cb0ef41Sopenharmony_ci return; 14111cb0ef41Sopenharmony_ci } 14121cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 14131cb0ef41Sopenharmony_ci Local<v8::Object> descriptor = Local<Object>::Cast(args[0]); 14141cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 14151cb0ef41Sopenharmony_ci 14161cb0ef41Sopenharmony_ci // The descriptor's 'mutable'. 14171cb0ef41Sopenharmony_ci bool is_mutable = false; 14181cb0ef41Sopenharmony_ci { 14191cb0ef41Sopenharmony_ci Local<String> mutable_key = v8_str(isolate, "mutable"); 14201cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key); 14211cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 14221cb0ef41Sopenharmony_ci if (maybe.ToLocal(&value)) { 14231cb0ef41Sopenharmony_ci is_mutable = value->BooleanValue(isolate); 14241cb0ef41Sopenharmony_ci } else { 14251cb0ef41Sopenharmony_ci DCHECK(i_isolate->has_scheduled_exception()); 14261cb0ef41Sopenharmony_ci return; 14271cb0ef41Sopenharmony_ci } 14281cb0ef41Sopenharmony_ci } 14291cb0ef41Sopenharmony_ci 14301cb0ef41Sopenharmony_ci // The descriptor's type, called 'value'. It is called 'value' because this 14311cb0ef41Sopenharmony_ci // descriptor is planned to be re-used as the global's type for reflection, 14321cb0ef41Sopenharmony_ci // so calling it 'type' is redundant. 14331cb0ef41Sopenharmony_ci i::wasm::ValueType type; 14341cb0ef41Sopenharmony_ci { 14351cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> maybe = 14361cb0ef41Sopenharmony_ci descriptor->Get(context, v8_str(isolate, "value")); 14371cb0ef41Sopenharmony_ci if (!GetValueType(isolate, maybe, context, &type, enabled_features)) return; 14381cb0ef41Sopenharmony_ci if (type == i::wasm::kWasmVoid) { 14391cb0ef41Sopenharmony_ci thrower.TypeError( 14401cb0ef41Sopenharmony_ci "Descriptor property 'value' must be a WebAssembly type"); 14411cb0ef41Sopenharmony_ci return; 14421cb0ef41Sopenharmony_ci } 14431cb0ef41Sopenharmony_ci } 14441cb0ef41Sopenharmony_ci 14451cb0ef41Sopenharmony_ci const uint32_t offset = 0; 14461cb0ef41Sopenharmony_ci i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj = 14471cb0ef41Sopenharmony_ci i::WasmGlobalObject::New(i_isolate, i::Handle<i::WasmInstanceObject>(), 14481cb0ef41Sopenharmony_ci i::MaybeHandle<i::JSArrayBuffer>(), 14491cb0ef41Sopenharmony_ci i::MaybeHandle<i::FixedArray>(), type, offset, 14501cb0ef41Sopenharmony_ci is_mutable); 14511cb0ef41Sopenharmony_ci 14521cb0ef41Sopenharmony_ci i::Handle<i::WasmGlobalObject> global_obj; 14531cb0ef41Sopenharmony_ci if (!maybe_global_obj.ToHandle(&global_obj)) { 14541cb0ef41Sopenharmony_ci thrower.RangeError("could not allocate memory"); 14551cb0ef41Sopenharmony_ci return; 14561cb0ef41Sopenharmony_ci } 14571cb0ef41Sopenharmony_ci 14581cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 14591cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 14601cb0ef41Sopenharmony_ci // and use {global_obj} instead, but it does have the correct prototype, 14611cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 14621cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Global} directly, but some 14631cb0ef41Sopenharmony_ci // subclass: {global_obj} has {WebAssembly.Global}'s prototype at this 14641cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 14651cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, global_obj, 14661cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 14671cb0ef41Sopenharmony_ci return; 14681cb0ef41Sopenharmony_ci } 14691cb0ef41Sopenharmony_ci 14701cb0ef41Sopenharmony_ci // Convert value to a WebAssembly value, the default value is 0. 14711cb0ef41Sopenharmony_ci Local<v8::Value> value = Local<Value>::Cast(args[1]); 14721cb0ef41Sopenharmony_ci switch (type.kind()) { 14731cb0ef41Sopenharmony_ci case i::wasm::kI32: { 14741cb0ef41Sopenharmony_ci int32_t i32_value = 0; 14751cb0ef41Sopenharmony_ci if (!ToI32(value, context, &i32_value)) return; 14761cb0ef41Sopenharmony_ci global_obj->SetI32(i32_value); 14771cb0ef41Sopenharmony_ci break; 14781cb0ef41Sopenharmony_ci } 14791cb0ef41Sopenharmony_ci case i::wasm::kI64: { 14801cb0ef41Sopenharmony_ci int64_t i64_value = 0; 14811cb0ef41Sopenharmony_ci if (!ToI64(value, context, &i64_value)) return; 14821cb0ef41Sopenharmony_ci global_obj->SetI64(i64_value); 14831cb0ef41Sopenharmony_ci break; 14841cb0ef41Sopenharmony_ci } 14851cb0ef41Sopenharmony_ci case i::wasm::kF32: { 14861cb0ef41Sopenharmony_ci float f32_value = 0; 14871cb0ef41Sopenharmony_ci if (!ToF32(value, context, &f32_value)) return; 14881cb0ef41Sopenharmony_ci global_obj->SetF32(f32_value); 14891cb0ef41Sopenharmony_ci break; 14901cb0ef41Sopenharmony_ci } 14911cb0ef41Sopenharmony_ci case i::wasm::kF64: { 14921cb0ef41Sopenharmony_ci double f64_value = 0; 14931cb0ef41Sopenharmony_ci if (!ToF64(value, context, &f64_value)) return; 14941cb0ef41Sopenharmony_ci global_obj->SetF64(f64_value); 14951cb0ef41Sopenharmony_ci break; 14961cb0ef41Sopenharmony_ci } 14971cb0ef41Sopenharmony_ci case i::wasm::kRef: 14981cb0ef41Sopenharmony_ci case i::wasm::kOptRef: { 14991cb0ef41Sopenharmony_ci switch (type.heap_representation()) { 15001cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: { 15011cb0ef41Sopenharmony_ci if (args.Length() < 2) { 15021cb0ef41Sopenharmony_ci // When no initial value is provided, we have to use the WebAssembly 15031cb0ef41Sopenharmony_ci // default value 'null', and not the JS default value 'undefined'. 15041cb0ef41Sopenharmony_ci global_obj->SetExternRef(i_isolate->factory()->null_value()); 15051cb0ef41Sopenharmony_ci break; 15061cb0ef41Sopenharmony_ci } 15071cb0ef41Sopenharmony_ci global_obj->SetExternRef(Utils::OpenHandle(*value)); 15081cb0ef41Sopenharmony_ci break; 15091cb0ef41Sopenharmony_ci } 15101cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: { 15111cb0ef41Sopenharmony_ci if (args.Length() < 2) { 15121cb0ef41Sopenharmony_ci // When no initial value is provided, we have to use the WebAssembly 15131cb0ef41Sopenharmony_ci // default value 'null', and not the JS default value 'undefined'. 15141cb0ef41Sopenharmony_ci global_obj->SetFuncRef(i_isolate, 15151cb0ef41Sopenharmony_ci i_isolate->factory()->null_value()); 15161cb0ef41Sopenharmony_ci break; 15171cb0ef41Sopenharmony_ci } 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_ci if (!global_obj->SetFuncRef(i_isolate, Utils::OpenHandle(*value))) { 15201cb0ef41Sopenharmony_ci thrower.TypeError( 15211cb0ef41Sopenharmony_ci "The value of funcref globals must be null or an " 15221cb0ef41Sopenharmony_ci "exported function"); 15231cb0ef41Sopenharmony_ci } 15241cb0ef41Sopenharmony_ci break; 15251cb0ef41Sopenharmony_ci } 15261cb0ef41Sopenharmony_ci case internal::wasm::HeapType::kBottom: 15271cb0ef41Sopenharmony_ci UNREACHABLE(); 15281cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 15291cb0ef41Sopenharmony_ci case internal::wasm::HeapType::kI31: 15301cb0ef41Sopenharmony_ci case internal::wasm::HeapType::kData: 15311cb0ef41Sopenharmony_ci case internal::wasm::HeapType::kArray: 15321cb0ef41Sopenharmony_ci default: 15331cb0ef41Sopenharmony_ci // TODO(7748): Implement these. 15341cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 15351cb0ef41Sopenharmony_ci } 15361cb0ef41Sopenharmony_ci break; 15371cb0ef41Sopenharmony_ci } 15381cb0ef41Sopenharmony_ci case i::wasm::kRtt: 15391cb0ef41Sopenharmony_ci // TODO(7748): Implement. 15401cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 15411cb0ef41Sopenharmony_ci case i::wasm::kI8: 15421cb0ef41Sopenharmony_ci case i::wasm::kI16: 15431cb0ef41Sopenharmony_ci case i::wasm::kVoid: 15441cb0ef41Sopenharmony_ci case i::wasm::kS128: 15451cb0ef41Sopenharmony_ci case i::wasm::kBottom: 15461cb0ef41Sopenharmony_ci UNREACHABLE(); 15471cb0ef41Sopenharmony_ci } 15481cb0ef41Sopenharmony_ci 15491cb0ef41Sopenharmony_ci i::Handle<i::JSObject> global_js_object(global_obj); 15501cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(global_js_object)); 15511cb0ef41Sopenharmony_ci} 15521cb0ef41Sopenharmony_ci 15531cb0ef41Sopenharmony_cinamespace { 15541cb0ef41Sopenharmony_ci 15551cb0ef41Sopenharmony_ciuint32_t GetIterableLength(i::Isolate* isolate, Local<Context> context, 15561cb0ef41Sopenharmony_ci Local<Object> iterable) { 15571cb0ef41Sopenharmony_ci Local<String> length = Utils::ToLocal(isolate->factory()->length_string()); 15581cb0ef41Sopenharmony_ci MaybeLocal<Value> property = iterable->Get(context, length); 15591cb0ef41Sopenharmony_ci if (property.IsEmpty()) return i::kMaxUInt32; 15601cb0ef41Sopenharmony_ci MaybeLocal<Uint32> number = property.ToLocalChecked()->ToArrayIndex(context); 15611cb0ef41Sopenharmony_ci if (number.IsEmpty()) return i::kMaxUInt32; 15621cb0ef41Sopenharmony_ci DCHECK_NE(i::kMaxUInt32, number.ToLocalChecked()->Value()); 15631cb0ef41Sopenharmony_ci return number.ToLocalChecked()->Value(); 15641cb0ef41Sopenharmony_ci} 15651cb0ef41Sopenharmony_ci 15661cb0ef41Sopenharmony_ci} // namespace 15671cb0ef41Sopenharmony_ci 15681cb0ef41Sopenharmony_ci// WebAssembly.Tag 15691cb0ef41Sopenharmony_civoid WebAssemblyTag(const v8::FunctionCallbackInfo<v8::Value>& args) { 15701cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 15711cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 15721cb0ef41Sopenharmony_ci HandleScope scope(isolate); 15731cb0ef41Sopenharmony_ci 15741cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Tag()"); 15751cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 15761cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Tag must be invoked with 'new'"); 15771cb0ef41Sopenharmony_ci return; 15781cb0ef41Sopenharmony_ci } 15791cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 15801cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a tag type"); 15811cb0ef41Sopenharmony_ci return; 15821cb0ef41Sopenharmony_ci } 15831cb0ef41Sopenharmony_ci 15841cb0ef41Sopenharmony_ci Local<Object> event_type = Local<Object>::Cast(args[0]); 15851cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 15861cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 15871cb0ef41Sopenharmony_ci 15881cb0ef41Sopenharmony_ci // Load the 'parameters' property of the event type. 15891cb0ef41Sopenharmony_ci Local<String> parameters_key = v8_str(isolate, "parameters"); 15901cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> parameters_maybe = 15911cb0ef41Sopenharmony_ci event_type->Get(context, parameters_key); 15921cb0ef41Sopenharmony_ci v8::Local<v8::Value> parameters_value; 15931cb0ef41Sopenharmony_ci if (!parameters_maybe.ToLocal(¶meters_value) || 15941cb0ef41Sopenharmony_ci !parameters_value->IsObject()) { 15951cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a tag type with 'parameters'"); 15961cb0ef41Sopenharmony_ci return; 15971cb0ef41Sopenharmony_ci } 15981cb0ef41Sopenharmony_ci Local<Object> parameters = parameters_value.As<Object>(); 15991cb0ef41Sopenharmony_ci uint32_t parameters_len = GetIterableLength(i_isolate, context, parameters); 16001cb0ef41Sopenharmony_ci if (parameters_len == i::kMaxUInt32) { 16011cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains parameters without 'length'"); 16021cb0ef41Sopenharmony_ci return; 16031cb0ef41Sopenharmony_ci } 16041cb0ef41Sopenharmony_ci if (parameters_len > i::wasm::kV8MaxWasmFunctionParams) { 16051cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains too many parameters"); 16061cb0ef41Sopenharmony_ci return; 16071cb0ef41Sopenharmony_ci } 16081cb0ef41Sopenharmony_ci 16091cb0ef41Sopenharmony_ci // Decode the tag type and construct a signature. 16101cb0ef41Sopenharmony_ci std::vector<i::wasm::ValueType> param_types(parameters_len, 16111cb0ef41Sopenharmony_ci i::wasm::kWasmVoid); 16121cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < parameters_len; ++i) { 16131cb0ef41Sopenharmony_ci i::wasm::ValueType& type = param_types[i]; 16141cb0ef41Sopenharmony_ci MaybeLocal<Value> maybe = parameters->Get(context, i); 16151cb0ef41Sopenharmony_ci if (!GetValueType(isolate, maybe, context, &type, enabled_features) || 16161cb0ef41Sopenharmony_ci type == i::wasm::kWasmVoid) { 16171cb0ef41Sopenharmony_ci thrower.TypeError( 16181cb0ef41Sopenharmony_ci "Argument 0 parameter type at index #%u must be a value type", i); 16191cb0ef41Sopenharmony_ci return; 16201cb0ef41Sopenharmony_ci } 16211cb0ef41Sopenharmony_ci } 16221cb0ef41Sopenharmony_ci const i::wasm::FunctionSig sig{0, parameters_len, param_types.data()}; 16231cb0ef41Sopenharmony_ci // Set the tag index to 0. It is only used for debugging purposes, and has no 16241cb0ef41Sopenharmony_ci // meaningful value when declared outside of a wasm module. 16251cb0ef41Sopenharmony_ci auto tag = i::WasmExceptionTag::New(i_isolate, 0); 16261cb0ef41Sopenharmony_ci i::Handle<i::JSObject> tag_object = 16271cb0ef41Sopenharmony_ci i::WasmTagObject::New(i_isolate, &sig, tag); 16281cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(tag_object)); 16291cb0ef41Sopenharmony_ci} 16301cb0ef41Sopenharmony_ci 16311cb0ef41Sopenharmony_ci// WebAssembly.Suspender 16321cb0ef41Sopenharmony_civoid WebAssemblySuspender(const v8::FunctionCallbackInfo<v8::Value>& args) { 16331cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 16341cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 16351cb0ef41Sopenharmony_ci HandleScope scope(isolate); 16361cb0ef41Sopenharmony_ci 16371cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Suspender()"); 16381cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 16391cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Suspender must be invoked with 'new'"); 16401cb0ef41Sopenharmony_ci return; 16411cb0ef41Sopenharmony_ci } 16421cb0ef41Sopenharmony_ci 16431cb0ef41Sopenharmony_ci i::Handle<i::JSObject> suspender = i::WasmSuspenderObject::New(i_isolate); 16441cb0ef41Sopenharmony_ci 16451cb0ef41Sopenharmony_ci // The infrastructure for `new Foo` calls allocates an object, which is 16461cb0ef41Sopenharmony_ci // available here as {args.This()}. We're going to discard this object 16471cb0ef41Sopenharmony_ci // and use {suspender} instead, but it does have the correct prototype, 16481cb0ef41Sopenharmony_ci // which we must harvest from it. This makes a difference when the JS 16491cb0ef41Sopenharmony_ci // constructor function wasn't {WebAssembly.Suspender} directly, but some 16501cb0ef41Sopenharmony_ci // subclass: {suspender} has {WebAssembly.Suspender}'s prototype at this 16511cb0ef41Sopenharmony_ci // point, so we must overwrite that with the correct prototype for {Foo}. 16521cb0ef41Sopenharmony_ci if (!TransferPrototype(i_isolate, suspender, 16531cb0ef41Sopenharmony_ci Utils::OpenHandle(*args.This()))) { 16541cb0ef41Sopenharmony_ci return; 16551cb0ef41Sopenharmony_ci } 16561cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(suspender)); 16571cb0ef41Sopenharmony_ci} 16581cb0ef41Sopenharmony_ci 16591cb0ef41Sopenharmony_cinamespace { 16601cb0ef41Sopenharmony_ci 16611cb0ef41Sopenharmony_ciuint32_t GetEncodedSize(i::Handle<i::WasmTagObject> tag_object) { 16621cb0ef41Sopenharmony_ci auto serialized_sig = tag_object->serialized_signature(); 16631cb0ef41Sopenharmony_ci i::wasm::WasmTagSig sig{0, static_cast<size_t>(serialized_sig.length()), 16641cb0ef41Sopenharmony_ci reinterpret_cast<i::wasm::ValueType*>( 16651cb0ef41Sopenharmony_ci serialized_sig.GetDataStartAddress())}; 16661cb0ef41Sopenharmony_ci i::wasm::WasmTag tag(&sig); 16671cb0ef41Sopenharmony_ci return i::WasmExceptionPackage::GetEncodedSize(&tag); 16681cb0ef41Sopenharmony_ci} 16691cb0ef41Sopenharmony_ci 16701cb0ef41Sopenharmony_civoid EncodeExceptionValues(v8::Isolate* isolate, 16711cb0ef41Sopenharmony_ci i::Handle<i::PodArray<i::wasm::ValueType>> signature, 16721cb0ef41Sopenharmony_ci const Local<Value>& arg, 16731cb0ef41Sopenharmony_ci ScheduledErrorThrower* thrower, 16741cb0ef41Sopenharmony_ci i::Handle<i::FixedArray> values_out) { 16751cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 16761cb0ef41Sopenharmony_ci uint32_t index = 0; 16771cb0ef41Sopenharmony_ci if (!arg->IsObject()) { 16781cb0ef41Sopenharmony_ci thrower->TypeError("Exception values must be an iterable object"); 16791cb0ef41Sopenharmony_ci return; 16801cb0ef41Sopenharmony_ci } 16811cb0ef41Sopenharmony_ci auto values = arg.As<Object>(); 16821cb0ef41Sopenharmony_ci for (int i = 0; i < signature->length(); ++i) { 16831cb0ef41Sopenharmony_ci MaybeLocal<Value> maybe_value = values->Get(context, i); 16841cb0ef41Sopenharmony_ci Local<Value> value = maybe_value.ToLocalChecked(); 16851cb0ef41Sopenharmony_ci i::wasm::ValueType type = signature->get(i); 16861cb0ef41Sopenharmony_ci switch (type.kind()) { 16871cb0ef41Sopenharmony_ci case i::wasm::kI32: { 16881cb0ef41Sopenharmony_ci int32_t i32 = 0; 16891cb0ef41Sopenharmony_ci if (!ToI32(value, context, &i32)) return; 16901cb0ef41Sopenharmony_ci i::EncodeI32ExceptionValue(values_out, &index, i32); 16911cb0ef41Sopenharmony_ci break; 16921cb0ef41Sopenharmony_ci } 16931cb0ef41Sopenharmony_ci case i::wasm::kI64: { 16941cb0ef41Sopenharmony_ci int64_t i64 = 0; 16951cb0ef41Sopenharmony_ci if (!ToI64(value, context, &i64)) return; 16961cb0ef41Sopenharmony_ci i::EncodeI64ExceptionValue(values_out, &index, i64); 16971cb0ef41Sopenharmony_ci break; 16981cb0ef41Sopenharmony_ci } 16991cb0ef41Sopenharmony_ci case i::wasm::kF32: { 17001cb0ef41Sopenharmony_ci float f32 = 0; 17011cb0ef41Sopenharmony_ci if (!ToF32(value, context, &f32)) return; 17021cb0ef41Sopenharmony_ci int32_t i32 = bit_cast<int32_t>(f32); 17031cb0ef41Sopenharmony_ci i::EncodeI32ExceptionValue(values_out, &index, i32); 17041cb0ef41Sopenharmony_ci break; 17051cb0ef41Sopenharmony_ci } 17061cb0ef41Sopenharmony_ci case i::wasm::kF64: { 17071cb0ef41Sopenharmony_ci double f64 = 0; 17081cb0ef41Sopenharmony_ci if (!ToF64(value, context, &f64)) return; 17091cb0ef41Sopenharmony_ci int64_t i64 = bit_cast<int64_t>(f64); 17101cb0ef41Sopenharmony_ci i::EncodeI64ExceptionValue(values_out, &index, i64); 17111cb0ef41Sopenharmony_ci break; 17121cb0ef41Sopenharmony_ci } 17131cb0ef41Sopenharmony_ci case i::wasm::kRef: 17141cb0ef41Sopenharmony_ci case i::wasm::kOptRef: 17151cb0ef41Sopenharmony_ci switch (type.heap_representation()) { 17161cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: 17171cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: 17181cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 17191cb0ef41Sopenharmony_ci case i::wasm::HeapType::kI31: 17201cb0ef41Sopenharmony_ci case i::wasm::HeapType::kData: 17211cb0ef41Sopenharmony_ci case i::wasm::HeapType::kArray: 17221cb0ef41Sopenharmony_ci values_out->set(index++, *Utils::OpenHandle(*value)); 17231cb0ef41Sopenharmony_ci break; 17241cb0ef41Sopenharmony_ci case internal::wasm::HeapType::kBottom: 17251cb0ef41Sopenharmony_ci UNREACHABLE(); 17261cb0ef41Sopenharmony_ci default: 17271cb0ef41Sopenharmony_ci // TODO(7748): Add support for custom struct/array types. 17281cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 17291cb0ef41Sopenharmony_ci } 17301cb0ef41Sopenharmony_ci break; 17311cb0ef41Sopenharmony_ci case i::wasm::kRtt: 17321cb0ef41Sopenharmony_ci case i::wasm::kI8: 17331cb0ef41Sopenharmony_ci case i::wasm::kI16: 17341cb0ef41Sopenharmony_ci case i::wasm::kVoid: 17351cb0ef41Sopenharmony_ci case i::wasm::kBottom: 17361cb0ef41Sopenharmony_ci case i::wasm::kS128: 17371cb0ef41Sopenharmony_ci UNREACHABLE(); 17381cb0ef41Sopenharmony_ci } 17391cb0ef41Sopenharmony_ci } 17401cb0ef41Sopenharmony_ci} 17411cb0ef41Sopenharmony_ci 17421cb0ef41Sopenharmony_ci} // namespace 17431cb0ef41Sopenharmony_ci 17441cb0ef41Sopenharmony_civoid WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) { 17451cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 17461cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 17471cb0ef41Sopenharmony_ci HandleScope scope(isolate); 17481cb0ef41Sopenharmony_ci 17491cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()"); 17501cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 17511cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Exception must be invoked with 'new'"); 17521cb0ef41Sopenharmony_ci return; 17531cb0ef41Sopenharmony_ci } 17541cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 17551cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a WebAssembly tag"); 17561cb0ef41Sopenharmony_ci return; 17571cb0ef41Sopenharmony_ci } 17581cb0ef41Sopenharmony_ci i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); 17591cb0ef41Sopenharmony_ci if (!i::HeapObject::cast(*arg0).IsWasmTagObject()) { 17601cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a WebAssembly tag"); 17611cb0ef41Sopenharmony_ci return; 17621cb0ef41Sopenharmony_ci } 17631cb0ef41Sopenharmony_ci i::Handle<i::WasmTagObject> tag_object = 17641cb0ef41Sopenharmony_ci i::Handle<i::WasmTagObject>::cast(arg0); 17651cb0ef41Sopenharmony_ci i::Handle<i::WasmExceptionTag> tag( 17661cb0ef41Sopenharmony_ci i::WasmExceptionTag::cast(tag_object->tag()), i_isolate); 17671cb0ef41Sopenharmony_ci uint32_t size = GetEncodedSize(tag_object); 17681cb0ef41Sopenharmony_ci i::Handle<i::WasmExceptionPackage> runtime_exception = 17691cb0ef41Sopenharmony_ci i::WasmExceptionPackage::New(i_isolate, tag, size); 17701cb0ef41Sopenharmony_ci // The constructor above should guarantee that the cast below succeeds. 17711cb0ef41Sopenharmony_ci i::Handle<i::FixedArray> values = i::Handle<i::FixedArray>::cast( 17721cb0ef41Sopenharmony_ci i::WasmExceptionPackage::GetExceptionValues(i_isolate, 17731cb0ef41Sopenharmony_ci runtime_exception)); 17741cb0ef41Sopenharmony_ci i::Handle<i::PodArray<i::wasm::ValueType>> signature( 17751cb0ef41Sopenharmony_ci tag_object->serialized_signature(), i_isolate); 17761cb0ef41Sopenharmony_ci EncodeExceptionValues(isolate, signature, args[1], &thrower, values); 17771cb0ef41Sopenharmony_ci if (thrower.error()) return; 17781cb0ef41Sopenharmony_ci args.GetReturnValue().Set( 17791cb0ef41Sopenharmony_ci Utils::ToLocal(i::Handle<i::Object>::cast(runtime_exception))); 17801cb0ef41Sopenharmony_ci} 17811cb0ef41Sopenharmony_ci 17821cb0ef41Sopenharmony_ci// WebAssembly.Function 17831cb0ef41Sopenharmony_civoid WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { 17841cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 17851cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 17861cb0ef41Sopenharmony_ci HandleScope scope(isolate); 17871cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function()"); 17881cb0ef41Sopenharmony_ci if (!args.IsConstructCall()) { 17891cb0ef41Sopenharmony_ci thrower.TypeError("WebAssembly.Function must be invoked with 'new'"); 17901cb0ef41Sopenharmony_ci return; 17911cb0ef41Sopenharmony_ci } 17921cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 17931cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a function type"); 17941cb0ef41Sopenharmony_ci return; 17951cb0ef41Sopenharmony_ci } 17961cb0ef41Sopenharmony_ci Local<Object> function_type = Local<Object>::Cast(args[0]); 17971cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 17981cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate); 17991cb0ef41Sopenharmony_ci 18001cb0ef41Sopenharmony_ci // Load the 'parameters' property of the function type. 18011cb0ef41Sopenharmony_ci Local<String> parameters_key = v8_str(isolate, "parameters"); 18021cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> parameters_maybe = 18031cb0ef41Sopenharmony_ci function_type->Get(context, parameters_key); 18041cb0ef41Sopenharmony_ci v8::Local<v8::Value> parameters_value; 18051cb0ef41Sopenharmony_ci if (!parameters_maybe.ToLocal(¶meters_value) || 18061cb0ef41Sopenharmony_ci !parameters_value->IsObject()) { 18071cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a function type with 'parameters'"); 18081cb0ef41Sopenharmony_ci return; 18091cb0ef41Sopenharmony_ci } 18101cb0ef41Sopenharmony_ci Local<Object> parameters = parameters_value.As<Object>(); 18111cb0ef41Sopenharmony_ci uint32_t parameters_len = GetIterableLength(i_isolate, context, parameters); 18121cb0ef41Sopenharmony_ci if (parameters_len == i::kMaxUInt32) { 18131cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains parameters without 'length'"); 18141cb0ef41Sopenharmony_ci return; 18151cb0ef41Sopenharmony_ci } 18161cb0ef41Sopenharmony_ci if (parameters_len > i::wasm::kV8MaxWasmFunctionParams) { 18171cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains too many parameters"); 18181cb0ef41Sopenharmony_ci return; 18191cb0ef41Sopenharmony_ci } 18201cb0ef41Sopenharmony_ci 18211cb0ef41Sopenharmony_ci // Load the 'results' property of the function type. 18221cb0ef41Sopenharmony_ci Local<String> results_key = v8_str(isolate, "results"); 18231cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> results_maybe = 18241cb0ef41Sopenharmony_ci function_type->Get(context, results_key); 18251cb0ef41Sopenharmony_ci v8::Local<v8::Value> results_value; 18261cb0ef41Sopenharmony_ci if (!results_maybe.ToLocal(&results_value)) return; 18271cb0ef41Sopenharmony_ci if (!results_value->IsObject()) { 18281cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a function type with 'results'"); 18291cb0ef41Sopenharmony_ci return; 18301cb0ef41Sopenharmony_ci } 18311cb0ef41Sopenharmony_ci Local<Object> results = results_value.As<Object>(); 18321cb0ef41Sopenharmony_ci uint32_t results_len = GetIterableLength(i_isolate, context, results); 18331cb0ef41Sopenharmony_ci if (results_len == i::kMaxUInt32) { 18341cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains results without 'length'"); 18351cb0ef41Sopenharmony_ci return; 18361cb0ef41Sopenharmony_ci } 18371cb0ef41Sopenharmony_ci if (results_len > i::wasm::kV8MaxWasmFunctionReturns) { 18381cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 contains too many results"); 18391cb0ef41Sopenharmony_ci return; 18401cb0ef41Sopenharmony_ci } 18411cb0ef41Sopenharmony_ci 18421cb0ef41Sopenharmony_ci // Decode the function type and construct a signature. 18431cb0ef41Sopenharmony_ci i::Zone zone(i_isolate->allocator(), ZONE_NAME); 18441cb0ef41Sopenharmony_ci i::wasm::FunctionSig::Builder builder(&zone, results_len, parameters_len); 18451cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < parameters_len; ++i) { 18461cb0ef41Sopenharmony_ci i::wasm::ValueType type; 18471cb0ef41Sopenharmony_ci MaybeLocal<Value> maybe = parameters->Get(context, i); 18481cb0ef41Sopenharmony_ci if (!GetValueType(isolate, maybe, context, &type, enabled_features) || 18491cb0ef41Sopenharmony_ci type == i::wasm::kWasmVoid) { 18501cb0ef41Sopenharmony_ci thrower.TypeError( 18511cb0ef41Sopenharmony_ci "Argument 0 parameter type at index #%u must be a value type", i); 18521cb0ef41Sopenharmony_ci return; 18531cb0ef41Sopenharmony_ci } 18541cb0ef41Sopenharmony_ci builder.AddParam(type); 18551cb0ef41Sopenharmony_ci } 18561cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < results_len; ++i) { 18571cb0ef41Sopenharmony_ci i::wasm::ValueType type; 18581cb0ef41Sopenharmony_ci MaybeLocal<Value> maybe = results->Get(context, i); 18591cb0ef41Sopenharmony_ci if (!GetValueType(isolate, maybe, context, &type, enabled_features)) return; 18601cb0ef41Sopenharmony_ci if (type == i::wasm::kWasmVoid) { 18611cb0ef41Sopenharmony_ci thrower.TypeError( 18621cb0ef41Sopenharmony_ci "Argument 0 result type at index #%u must be a value type", i); 18631cb0ef41Sopenharmony_ci return; 18641cb0ef41Sopenharmony_ci } 18651cb0ef41Sopenharmony_ci builder.AddReturn(type); 18661cb0ef41Sopenharmony_ci } 18671cb0ef41Sopenharmony_ci 18681cb0ef41Sopenharmony_ci if (!args[1]->IsFunction()) { 18691cb0ef41Sopenharmony_ci thrower.TypeError("Argument 1 must be a function"); 18701cb0ef41Sopenharmony_ci return; 18711cb0ef41Sopenharmony_ci } 18721cb0ef41Sopenharmony_ci const i::wasm::FunctionSig* sig = builder.Build(); 18731cb0ef41Sopenharmony_ci 18741cb0ef41Sopenharmony_ci i::Handle<i::JSReceiver> callable = 18751cb0ef41Sopenharmony_ci Utils::OpenHandle(*args[1].As<Function>()); 18761cb0ef41Sopenharmony_ci if (i::WasmExportedFunction::IsWasmExportedFunction(*callable)) { 18771cb0ef41Sopenharmony_ci if (*i::Handle<i::WasmExportedFunction>::cast(callable)->sig() == *sig) { 18781cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(callable)); 18791cb0ef41Sopenharmony_ci return; 18801cb0ef41Sopenharmony_ci } 18811cb0ef41Sopenharmony_ci 18821cb0ef41Sopenharmony_ci thrower.TypeError( 18831cb0ef41Sopenharmony_ci "The signature of Argument 1 (a WebAssembly function) does " 18841cb0ef41Sopenharmony_ci "not match the signature specified in Argument 0"); 18851cb0ef41Sopenharmony_ci return; 18861cb0ef41Sopenharmony_ci } 18871cb0ef41Sopenharmony_ci 18881cb0ef41Sopenharmony_ci if (i::WasmJSFunction::IsWasmJSFunction(*callable)) { 18891cb0ef41Sopenharmony_ci if (i::Handle<i::WasmJSFunction>::cast(callable)->MatchesSignature(sig)) { 18901cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(callable)); 18911cb0ef41Sopenharmony_ci return; 18921cb0ef41Sopenharmony_ci } 18931cb0ef41Sopenharmony_ci 18941cb0ef41Sopenharmony_ci thrower.TypeError( 18951cb0ef41Sopenharmony_ci "The signature of Argument 1 (a WebAssembly function) does " 18961cb0ef41Sopenharmony_ci "not match the signature specified in Argument 0"); 18971cb0ef41Sopenharmony_ci return; 18981cb0ef41Sopenharmony_ci } 18991cb0ef41Sopenharmony_ci 19001cb0ef41Sopenharmony_ci i::Handle<i::JSFunction> result = i::WasmJSFunction::New( 19011cb0ef41Sopenharmony_ci i_isolate, sig, callable, i::Handle<i::HeapObject>()); 19021cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(result)); 19031cb0ef41Sopenharmony_ci} 19041cb0ef41Sopenharmony_ci 19051cb0ef41Sopenharmony_ci// WebAssembly.Function.type(WebAssembly.Function) -> FunctionType 19061cb0ef41Sopenharmony_civoid WebAssemblyFunctionType(const v8::FunctionCallbackInfo<v8::Value>& args) { 19071cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 19081cb0ef41Sopenharmony_ci HandleScope scope(isolate); 19091cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 19101cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function.type()"); 19111cb0ef41Sopenharmony_ci 19121cb0ef41Sopenharmony_ci const i::wasm::FunctionSig* sig; 19131cb0ef41Sopenharmony_ci i::Zone zone(i_isolate->allocator(), ZONE_NAME); 19141cb0ef41Sopenharmony_ci i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); 19151cb0ef41Sopenharmony_ci if (i::WasmExportedFunction::IsWasmExportedFunction(*arg0)) { 19161cb0ef41Sopenharmony_ci auto wasm_exported_function = 19171cb0ef41Sopenharmony_ci i::Handle<i::WasmExportedFunction>::cast(arg0); 19181cb0ef41Sopenharmony_ci auto sfi = handle(wasm_exported_function->shared(), i_isolate); 19191cb0ef41Sopenharmony_ci i::Handle<i::WasmExportedFunctionData> data = 19201cb0ef41Sopenharmony_ci handle(sfi->wasm_exported_function_data(), i_isolate); 19211cb0ef41Sopenharmony_ci sig = wasm_exported_function->sig(); 19221cb0ef41Sopenharmony_ci if (!data->suspender().IsUndefined()) { 19231cb0ef41Sopenharmony_ci // If this export is wrapped by a Suspender, the function returns a 19241cb0ef41Sopenharmony_ci // promise as an externref instead of the original return type. 19251cb0ef41Sopenharmony_ci size_t param_count = sig->parameter_count(); 19261cb0ef41Sopenharmony_ci i::wasm::FunctionSig::Builder builder(&zone, 1, param_count); 19271cb0ef41Sopenharmony_ci for (size_t i = 0; i < param_count; ++i) { 19281cb0ef41Sopenharmony_ci builder.AddParam(sig->GetParam(0)); 19291cb0ef41Sopenharmony_ci } 19301cb0ef41Sopenharmony_ci builder.AddReturn(i::wasm::kWasmAnyRef); 19311cb0ef41Sopenharmony_ci sig = builder.Build(); 19321cb0ef41Sopenharmony_ci } 19331cb0ef41Sopenharmony_ci } else if (i::WasmJSFunction::IsWasmJSFunction(*arg0)) { 19341cb0ef41Sopenharmony_ci sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone); 19351cb0ef41Sopenharmony_ci } else { 19361cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a WebAssembly.Function"); 19371cb0ef41Sopenharmony_ci return; 19381cb0ef41Sopenharmony_ci } 19391cb0ef41Sopenharmony_ci 19401cb0ef41Sopenharmony_ci auto type = i::wasm::GetTypeForFunction(i_isolate, sig); 19411cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(type)); 19421cb0ef41Sopenharmony_ci} 19431cb0ef41Sopenharmony_ci 19441cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmGlobalObject = "WebAssembly.Global"; 19451cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory"; 19461cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance"; 19471cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmSuspenderObject = "WebAssembly.Suspender"; 19481cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmTableObject = "WebAssembly.Table"; 19491cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmTagObject = "WebAssembly.Tag"; 19501cb0ef41Sopenharmony_ciconstexpr const char* kName_WasmExceptionPackage = "WebAssembly.Exception"; 19511cb0ef41Sopenharmony_ci 19521cb0ef41Sopenharmony_ci#define EXTRACT_THIS(var, WasmType) \ 19531cb0ef41Sopenharmony_ci i::Handle<i::WasmType> var; \ 19541cb0ef41Sopenharmony_ci { \ 19551cb0ef41Sopenharmony_ci i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \ 19561cb0ef41Sopenharmony_ci if (!this_arg->Is##WasmType()) { \ 19571cb0ef41Sopenharmony_ci thrower.TypeError("Receiver is not a %s", kName_##WasmType); \ 19581cb0ef41Sopenharmony_ci return; \ 19591cb0ef41Sopenharmony_ci } \ 19601cb0ef41Sopenharmony_ci var = i::Handle<i::WasmType>::cast(this_arg); \ 19611cb0ef41Sopenharmony_ci } 19621cb0ef41Sopenharmony_ci 19631cb0ef41Sopenharmony_civoid WebAssemblyInstanceGetExports( 19641cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 19651cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 19661cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 19671cb0ef41Sopenharmony_ci HandleScope scope(isolate); 19681cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()"); 19691cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmInstanceObject); 19701cb0ef41Sopenharmony_ci i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate); 19711cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(exports_object)); 19721cb0ef41Sopenharmony_ci} 19731cb0ef41Sopenharmony_ci 19741cb0ef41Sopenharmony_civoid WebAssemblyTableGetLength( 19751cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 19761cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 19771cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 19781cb0ef41Sopenharmony_ci HandleScope scope(isolate); 19791cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()"); 19801cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmTableObject); 19811cb0ef41Sopenharmony_ci args.GetReturnValue().Set( 19821cb0ef41Sopenharmony_ci v8::Number::New(isolate, receiver->current_length())); 19831cb0ef41Sopenharmony_ci} 19841cb0ef41Sopenharmony_ci 19851cb0ef41Sopenharmony_ci// WebAssembly.Table.grow(num, init_value = null) -> num 19861cb0ef41Sopenharmony_civoid WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { 19871cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 19881cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 19891cb0ef41Sopenharmony_ci HandleScope scope(isolate); 19901cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()"); 19911cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 19921cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmTableObject); 19931cb0ef41Sopenharmony_ci 19941cb0ef41Sopenharmony_ci uint32_t grow_by; 19951cb0ef41Sopenharmony_ci if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) { 19961cb0ef41Sopenharmony_ci return; 19971cb0ef41Sopenharmony_ci } 19981cb0ef41Sopenharmony_ci 19991cb0ef41Sopenharmony_ci i::Handle<i::Object> init_value; 20001cb0ef41Sopenharmony_ci 20011cb0ef41Sopenharmony_ci if (args.Length() >= 2 && !args[1]->IsUndefined()) { 20021cb0ef41Sopenharmony_ci init_value = Utils::OpenHandle(*args[1]); 20031cb0ef41Sopenharmony_ci if (!i::WasmTableObject::IsValidElement(i_isolate, receiver, init_value)) { 20041cb0ef41Sopenharmony_ci thrower.TypeError("Argument 1 must be a valid type for the table"); 20051cb0ef41Sopenharmony_ci return; 20061cb0ef41Sopenharmony_ci } 20071cb0ef41Sopenharmony_ci } else { 20081cb0ef41Sopenharmony_ci init_value = DefaultReferenceValue(i_isolate, receiver->type()); 20091cb0ef41Sopenharmony_ci } 20101cb0ef41Sopenharmony_ci 20111cb0ef41Sopenharmony_ci // TODO(7748): Generalize this if other table types are allowed. 20121cb0ef41Sopenharmony_ci bool has_function_type = 20131cb0ef41Sopenharmony_ci receiver->type() == i::wasm::kWasmFuncRef || receiver->type().has_index(); 20141cb0ef41Sopenharmony_ci if (has_function_type && !init_value->IsNull()) { 20151cb0ef41Sopenharmony_ci init_value = i::WasmInternalFunction::FromExternal(init_value, i_isolate) 20161cb0ef41Sopenharmony_ci .ToHandleChecked(); 20171cb0ef41Sopenharmony_ci } 20181cb0ef41Sopenharmony_ci 20191cb0ef41Sopenharmony_ci int old_size = 20201cb0ef41Sopenharmony_ci i::WasmTableObject::Grow(i_isolate, receiver, grow_by, init_value); 20211cb0ef41Sopenharmony_ci 20221cb0ef41Sopenharmony_ci if (old_size < 0) { 20231cb0ef41Sopenharmony_ci thrower.RangeError("failed to grow table by %u", grow_by); 20241cb0ef41Sopenharmony_ci return; 20251cb0ef41Sopenharmony_ci } 20261cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 20271cb0ef41Sopenharmony_ci return_value.Set(old_size); 20281cb0ef41Sopenharmony_ci} 20291cb0ef41Sopenharmony_ci 20301cb0ef41Sopenharmony_ci// WebAssembly.Table.get(num) -> any 20311cb0ef41Sopenharmony_civoid WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { 20321cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 20331cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 20341cb0ef41Sopenharmony_ci HandleScope scope(isolate); 20351cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()"); 20361cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 20371cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmTableObject); 20381cb0ef41Sopenharmony_ci 20391cb0ef41Sopenharmony_ci uint32_t index; 20401cb0ef41Sopenharmony_ci if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) { 20411cb0ef41Sopenharmony_ci return; 20421cb0ef41Sopenharmony_ci } 20431cb0ef41Sopenharmony_ci if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) { 20441cb0ef41Sopenharmony_ci thrower.RangeError("invalid index %u into function table", index); 20451cb0ef41Sopenharmony_ci return; 20461cb0ef41Sopenharmony_ci } 20471cb0ef41Sopenharmony_ci 20481cb0ef41Sopenharmony_ci i::Handle<i::Object> result = 20491cb0ef41Sopenharmony_ci i::WasmTableObject::Get(i_isolate, receiver, index); 20501cb0ef41Sopenharmony_ci if (result->IsWasmInternalFunction()) { 20511cb0ef41Sopenharmony_ci result = 20521cb0ef41Sopenharmony_ci handle(i::Handle<i::WasmInternalFunction>::cast(result)->external(), 20531cb0ef41Sopenharmony_ci i_isolate); 20541cb0ef41Sopenharmony_ci } 20551cb0ef41Sopenharmony_ci 20561cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 20571cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(result)); 20581cb0ef41Sopenharmony_ci} 20591cb0ef41Sopenharmony_ci 20601cb0ef41Sopenharmony_ci// WebAssembly.Table.set(num, any) 20611cb0ef41Sopenharmony_civoid WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { 20621cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 20631cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 20641cb0ef41Sopenharmony_ci HandleScope scope(isolate); 20651cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()"); 20661cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 20671cb0ef41Sopenharmony_ci EXTRACT_THIS(table_object, WasmTableObject); 20681cb0ef41Sopenharmony_ci 20691cb0ef41Sopenharmony_ci // Parameter 0. 20701cb0ef41Sopenharmony_ci uint32_t index; 20711cb0ef41Sopenharmony_ci if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) { 20721cb0ef41Sopenharmony_ci return; 20731cb0ef41Sopenharmony_ci } 20741cb0ef41Sopenharmony_ci if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) { 20751cb0ef41Sopenharmony_ci thrower.RangeError("invalid index %u into function table", index); 20761cb0ef41Sopenharmony_ci return; 20771cb0ef41Sopenharmony_ci } 20781cb0ef41Sopenharmony_ci 20791cb0ef41Sopenharmony_ci i::Handle<i::Object> element = 20801cb0ef41Sopenharmony_ci args.Length() >= 2 20811cb0ef41Sopenharmony_ci ? Utils::OpenHandle(*args[1]) 20821cb0ef41Sopenharmony_ci : DefaultReferenceValue(i_isolate, table_object->type()); 20831cb0ef41Sopenharmony_ci 20841cb0ef41Sopenharmony_ci if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) { 20851cb0ef41Sopenharmony_ci thrower.TypeError("Argument 1 is invalid for table of type %s", 20861cb0ef41Sopenharmony_ci table_object->type().name().c_str()); 20871cb0ef41Sopenharmony_ci return; 20881cb0ef41Sopenharmony_ci } 20891cb0ef41Sopenharmony_ci 20901cb0ef41Sopenharmony_ci i::Handle<i::Object> external_element; 20911cb0ef41Sopenharmony_ci bool is_external = i::WasmInternalFunction::FromExternal(element, i_isolate) 20921cb0ef41Sopenharmony_ci .ToHandle(&external_element); 20931cb0ef41Sopenharmony_ci 20941cb0ef41Sopenharmony_ci i::WasmTableObject::Set(i_isolate, table_object, index, 20951cb0ef41Sopenharmony_ci is_external ? external_element : element); 20961cb0ef41Sopenharmony_ci} 20971cb0ef41Sopenharmony_ci 20981cb0ef41Sopenharmony_ci// WebAssembly.Table.type() -> TableType 20991cb0ef41Sopenharmony_civoid WebAssemblyTableType(const v8::FunctionCallbackInfo<v8::Value>& args) { 21001cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 21011cb0ef41Sopenharmony_ci HandleScope scope(isolate); 21021cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 21031cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()"); 21041cb0ef41Sopenharmony_ci 21051cb0ef41Sopenharmony_ci EXTRACT_THIS(table, WasmTableObject); 21061cb0ef41Sopenharmony_ci base::Optional<uint32_t> max_size; 21071cb0ef41Sopenharmony_ci if (!table->maximum_length().IsUndefined()) { 21081cb0ef41Sopenharmony_ci uint64_t max_size64 = table->maximum_length().Number(); 21091cb0ef41Sopenharmony_ci DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max()); 21101cb0ef41Sopenharmony_ci max_size.emplace(static_cast<uint32_t>(max_size64)); 21111cb0ef41Sopenharmony_ci } 21121cb0ef41Sopenharmony_ci auto type = i::wasm::GetTypeForTable(i_isolate, table->type(), 21131cb0ef41Sopenharmony_ci table->current_length(), max_size); 21141cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(type)); 21151cb0ef41Sopenharmony_ci} 21161cb0ef41Sopenharmony_ci 21171cb0ef41Sopenharmony_ci// WebAssembly.Memory.grow(num) -> num 21181cb0ef41Sopenharmony_civoid WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { 21191cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 21201cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 21211cb0ef41Sopenharmony_ci HandleScope scope(isolate); 21221cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()"); 21231cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 21241cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmMemoryObject); 21251cb0ef41Sopenharmony_ci 21261cb0ef41Sopenharmony_ci uint32_t delta_pages; 21271cb0ef41Sopenharmony_ci if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_pages)) { 21281cb0ef41Sopenharmony_ci return; 21291cb0ef41Sopenharmony_ci } 21301cb0ef41Sopenharmony_ci 21311cb0ef41Sopenharmony_ci i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate); 21321cb0ef41Sopenharmony_ci 21331cb0ef41Sopenharmony_ci uint64_t old_pages64 = old_buffer->byte_length() / i::wasm::kWasmPageSize; 21341cb0ef41Sopenharmony_ci uint64_t new_pages64 = old_pages64 + static_cast<uint64_t>(delta_pages); 21351cb0ef41Sopenharmony_ci 21361cb0ef41Sopenharmony_ci if (new_pages64 > static_cast<uint64_t>(receiver->maximum_pages())) { 21371cb0ef41Sopenharmony_ci thrower.RangeError("Maximum memory size exceeded"); 21381cb0ef41Sopenharmony_ci return; 21391cb0ef41Sopenharmony_ci } 21401cb0ef41Sopenharmony_ci 21411cb0ef41Sopenharmony_ci int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_pages); 21421cb0ef41Sopenharmony_ci if (ret == -1) { 21431cb0ef41Sopenharmony_ci thrower.RangeError("Unable to grow instance memory"); 21441cb0ef41Sopenharmony_ci return; 21451cb0ef41Sopenharmony_ci } 21461cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 21471cb0ef41Sopenharmony_ci return_value.Set(ret); 21481cb0ef41Sopenharmony_ci} 21491cb0ef41Sopenharmony_ci 21501cb0ef41Sopenharmony_ci// WebAssembly.Memory.buffer -> ArrayBuffer 21511cb0ef41Sopenharmony_civoid WebAssemblyMemoryGetBuffer( 21521cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 21531cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 21541cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 21551cb0ef41Sopenharmony_ci HandleScope scope(isolate); 21561cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer"); 21571cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmMemoryObject); 21581cb0ef41Sopenharmony_ci 21591cb0ef41Sopenharmony_ci i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate); 21601cb0ef41Sopenharmony_ci DCHECK(buffer_obj->IsJSArrayBuffer()); 21611cb0ef41Sopenharmony_ci i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj), 21621cb0ef41Sopenharmony_ci i_isolate); 21631cb0ef41Sopenharmony_ci if (buffer->is_shared()) { 21641cb0ef41Sopenharmony_ci // TODO(gdeepti): More needed here for when cached buffer, and current 21651cb0ef41Sopenharmony_ci // buffer are out of sync, handle that here when bounds checks, and Grow 21661cb0ef41Sopenharmony_ci // are handled correctly. 21671cb0ef41Sopenharmony_ci Maybe<bool> result = 21681cb0ef41Sopenharmony_ci buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow); 21691cb0ef41Sopenharmony_ci if (!result.FromJust()) { 21701cb0ef41Sopenharmony_ci thrower.TypeError( 21711cb0ef41Sopenharmony_ci "Status of setting SetIntegrityLevel of buffer is false."); 21721cb0ef41Sopenharmony_ci } 21731cb0ef41Sopenharmony_ci } 21741cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 21751cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(buffer)); 21761cb0ef41Sopenharmony_ci} 21771cb0ef41Sopenharmony_ci 21781cb0ef41Sopenharmony_ci// WebAssembly.Memory.type() -> MemoryType 21791cb0ef41Sopenharmony_civoid WebAssemblyMemoryType(const v8::FunctionCallbackInfo<v8::Value>& args) { 21801cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 21811cb0ef41Sopenharmony_ci HandleScope scope(isolate); 21821cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 21831cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()"); 21841cb0ef41Sopenharmony_ci 21851cb0ef41Sopenharmony_ci EXTRACT_THIS(memory, WasmMemoryObject); 21861cb0ef41Sopenharmony_ci i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate); 21871cb0ef41Sopenharmony_ci size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize; 21881cb0ef41Sopenharmony_ci DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max()); 21891cb0ef41Sopenharmony_ci uint32_t min_size = static_cast<uint32_t>(curr_size); 21901cb0ef41Sopenharmony_ci base::Optional<uint32_t> max_size; 21911cb0ef41Sopenharmony_ci if (memory->has_maximum_pages()) { 21921cb0ef41Sopenharmony_ci uint64_t max_size64 = memory->maximum_pages(); 21931cb0ef41Sopenharmony_ci DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max()); 21941cb0ef41Sopenharmony_ci max_size.emplace(static_cast<uint32_t>(max_size64)); 21951cb0ef41Sopenharmony_ci } 21961cb0ef41Sopenharmony_ci bool shared = buffer->is_shared(); 21971cb0ef41Sopenharmony_ci auto type = i::wasm::GetTypeForMemory(i_isolate, min_size, max_size, shared); 21981cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(type)); 21991cb0ef41Sopenharmony_ci} 22001cb0ef41Sopenharmony_ci 22011cb0ef41Sopenharmony_ci// WebAssembly.Tag.type() -> FunctionType 22021cb0ef41Sopenharmony_civoid WebAssemblyTagType(const v8::FunctionCallbackInfo<v8::Value>& args) { 22031cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 22041cb0ef41Sopenharmony_ci HandleScope scope(isolate); 22051cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 22061cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Tag.type()"); 22071cb0ef41Sopenharmony_ci 22081cb0ef41Sopenharmony_ci EXTRACT_THIS(tag, WasmTagObject); 22091cb0ef41Sopenharmony_ci if (thrower.error()) return; 22101cb0ef41Sopenharmony_ci 22111cb0ef41Sopenharmony_ci int n = tag->serialized_signature().length(); 22121cb0ef41Sopenharmony_ci std::vector<i::wasm::ValueType> data(n); 22131cb0ef41Sopenharmony_ci if (n > 0) { 22141cb0ef41Sopenharmony_ci tag->serialized_signature().copy_out(0, data.data(), n); 22151cb0ef41Sopenharmony_ci } 22161cb0ef41Sopenharmony_ci const i::wasm::FunctionSig sig{0, data.size(), data.data()}; 22171cb0ef41Sopenharmony_ci constexpr bool kForException = true; 22181cb0ef41Sopenharmony_ci auto type = i::wasm::GetTypeForFunction(i_isolate, &sig, kForException); 22191cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(type)); 22201cb0ef41Sopenharmony_ci} 22211cb0ef41Sopenharmony_ci 22221cb0ef41Sopenharmony_civoid WebAssemblyExceptionGetArg( 22231cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 22241cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 22251cb0ef41Sopenharmony_ci HandleScope scope(isolate); 22261cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 22271cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception.getArg()"); 22281cb0ef41Sopenharmony_ci 22291cb0ef41Sopenharmony_ci EXTRACT_THIS(exception, WasmExceptionPackage); 22301cb0ef41Sopenharmony_ci if (thrower.error()) return; 22311cb0ef41Sopenharmony_ci 22321cb0ef41Sopenharmony_ci i::MaybeHandle<i::WasmTagObject> maybe_tag = 22331cb0ef41Sopenharmony_ci GetFirstArgumentAsTag(args, &thrower); 22341cb0ef41Sopenharmony_ci if (thrower.error()) return; 22351cb0ef41Sopenharmony_ci auto tag = maybe_tag.ToHandleChecked(); 22361cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 22371cb0ef41Sopenharmony_ci uint32_t index; 22381cb0ef41Sopenharmony_ci if (!EnforceUint32("Index", args[1], context, &thrower, &index)) { 22391cb0ef41Sopenharmony_ci return; 22401cb0ef41Sopenharmony_ci } 22411cb0ef41Sopenharmony_ci auto maybe_values = 22421cb0ef41Sopenharmony_ci i::WasmExceptionPackage::GetExceptionValues(i_isolate, exception); 22431cb0ef41Sopenharmony_ci 22441cb0ef41Sopenharmony_ci auto this_tag = 22451cb0ef41Sopenharmony_ci i::WasmExceptionPackage::GetExceptionTag(i_isolate, exception); 22461cb0ef41Sopenharmony_ci if (this_tag->IsUndefined()) { 22471cb0ef41Sopenharmony_ci thrower.TypeError("Expected a WebAssembly.Exception object"); 22481cb0ef41Sopenharmony_ci return; 22491cb0ef41Sopenharmony_ci } 22501cb0ef41Sopenharmony_ci DCHECK(this_tag->IsWasmExceptionTag()); 22511cb0ef41Sopenharmony_ci if (tag->tag() != *this_tag) { 22521cb0ef41Sopenharmony_ci thrower.TypeError("First argument does not match the exception tag"); 22531cb0ef41Sopenharmony_ci return; 22541cb0ef41Sopenharmony_ci } 22551cb0ef41Sopenharmony_ci 22561cb0ef41Sopenharmony_ci DCHECK(!maybe_values->IsUndefined()); 22571cb0ef41Sopenharmony_ci auto values = i::Handle<i::FixedArray>::cast(maybe_values); 22581cb0ef41Sopenharmony_ci auto signature = tag->serialized_signature(); 22591cb0ef41Sopenharmony_ci if (index >= static_cast<uint32_t>(signature.length())) { 22601cb0ef41Sopenharmony_ci thrower.RangeError("Index out of range"); 22611cb0ef41Sopenharmony_ci return; 22621cb0ef41Sopenharmony_ci } 22631cb0ef41Sopenharmony_ci // First, find the index in the values array. 22641cb0ef41Sopenharmony_ci uint32_t decode_index = 0; 22651cb0ef41Sopenharmony_ci // Since the bounds check above passed, the cast to int is safe. 22661cb0ef41Sopenharmony_ci for (int i = 0; i < static_cast<int>(index); ++i) { 22671cb0ef41Sopenharmony_ci switch (signature.get(i).kind()) { 22681cb0ef41Sopenharmony_ci case i::wasm::kI32: 22691cb0ef41Sopenharmony_ci case i::wasm::kF32: 22701cb0ef41Sopenharmony_ci decode_index += 2; 22711cb0ef41Sopenharmony_ci break; 22721cb0ef41Sopenharmony_ci case i::wasm::kI64: 22731cb0ef41Sopenharmony_ci case i::wasm::kF64: 22741cb0ef41Sopenharmony_ci decode_index += 4; 22751cb0ef41Sopenharmony_ci break; 22761cb0ef41Sopenharmony_ci case i::wasm::kRef: 22771cb0ef41Sopenharmony_ci case i::wasm::kOptRef: 22781cb0ef41Sopenharmony_ci switch (signature.get(i).heap_representation()) { 22791cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: 22801cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: 22811cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 22821cb0ef41Sopenharmony_ci case i::wasm::HeapType::kI31: 22831cb0ef41Sopenharmony_ci case i::wasm::HeapType::kData: 22841cb0ef41Sopenharmony_ci case i::wasm::HeapType::kArray: 22851cb0ef41Sopenharmony_ci decode_index++; 22861cb0ef41Sopenharmony_ci break; 22871cb0ef41Sopenharmony_ci case i::wasm::HeapType::kBottom: 22881cb0ef41Sopenharmony_ci UNREACHABLE(); 22891cb0ef41Sopenharmony_ci default: 22901cb0ef41Sopenharmony_ci // TODO(7748): Add support for custom struct/array types. 22911cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 22921cb0ef41Sopenharmony_ci } 22931cb0ef41Sopenharmony_ci break; 22941cb0ef41Sopenharmony_ci case i::wasm::kRtt: 22951cb0ef41Sopenharmony_ci case i::wasm::kI8: 22961cb0ef41Sopenharmony_ci case i::wasm::kI16: 22971cb0ef41Sopenharmony_ci case i::wasm::kVoid: 22981cb0ef41Sopenharmony_ci case i::wasm::kBottom: 22991cb0ef41Sopenharmony_ci case i::wasm::kS128: 23001cb0ef41Sopenharmony_ci UNREACHABLE(); 23011cb0ef41Sopenharmony_ci } 23021cb0ef41Sopenharmony_ci } 23031cb0ef41Sopenharmony_ci // Decode the value at {decode_index}. 23041cb0ef41Sopenharmony_ci Local<Value> result; 23051cb0ef41Sopenharmony_ci switch (signature.get(index).kind()) { 23061cb0ef41Sopenharmony_ci case i::wasm::kI32: { 23071cb0ef41Sopenharmony_ci uint32_t u32_bits = 0; 23081cb0ef41Sopenharmony_ci i::DecodeI32ExceptionValue(values, &decode_index, &u32_bits); 23091cb0ef41Sopenharmony_ci int32_t i32 = static_cast<int32_t>(u32_bits); 23101cb0ef41Sopenharmony_ci result = v8::Integer::New(isolate, i32); 23111cb0ef41Sopenharmony_ci break; 23121cb0ef41Sopenharmony_ci } 23131cb0ef41Sopenharmony_ci case i::wasm::kI64: { 23141cb0ef41Sopenharmony_ci uint64_t u64_bits = 0; 23151cb0ef41Sopenharmony_ci i::DecodeI64ExceptionValue(values, &decode_index, &u64_bits); 23161cb0ef41Sopenharmony_ci int64_t i64 = static_cast<int64_t>(u64_bits); 23171cb0ef41Sopenharmony_ci result = v8::BigInt::New(isolate, i64); 23181cb0ef41Sopenharmony_ci break; 23191cb0ef41Sopenharmony_ci } 23201cb0ef41Sopenharmony_ci case i::wasm::kF32: { 23211cb0ef41Sopenharmony_ci uint32_t f32_bits = 0; 23221cb0ef41Sopenharmony_ci DecodeI32ExceptionValue(values, &decode_index, &f32_bits); 23231cb0ef41Sopenharmony_ci float f32 = bit_cast<float>(f32_bits); 23241cb0ef41Sopenharmony_ci result = v8::Number::New(isolate, f32); 23251cb0ef41Sopenharmony_ci break; 23261cb0ef41Sopenharmony_ci } 23271cb0ef41Sopenharmony_ci case i::wasm::kF64: { 23281cb0ef41Sopenharmony_ci uint64_t f64_bits = 0; 23291cb0ef41Sopenharmony_ci DecodeI64ExceptionValue(values, &decode_index, &f64_bits); 23301cb0ef41Sopenharmony_ci double f64 = bit_cast<double>(f64_bits); 23311cb0ef41Sopenharmony_ci result = v8::Number::New(isolate, f64); 23321cb0ef41Sopenharmony_ci break; 23331cb0ef41Sopenharmony_ci } 23341cb0ef41Sopenharmony_ci case i::wasm::kRef: 23351cb0ef41Sopenharmony_ci case i::wasm::kOptRef: 23361cb0ef41Sopenharmony_ci switch (signature.get(index).heap_representation()) { 23371cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: 23381cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: 23391cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 23401cb0ef41Sopenharmony_ci case i::wasm::HeapType::kI31: 23411cb0ef41Sopenharmony_ci case i::wasm::HeapType::kArray: 23421cb0ef41Sopenharmony_ci case i::wasm::HeapType::kData: { 23431cb0ef41Sopenharmony_ci auto obj = values->get(decode_index); 23441cb0ef41Sopenharmony_ci result = Utils::ToLocal(i::Handle<i::Object>(obj, i_isolate)); 23451cb0ef41Sopenharmony_ci break; 23461cb0ef41Sopenharmony_ci } 23471cb0ef41Sopenharmony_ci case i::wasm::HeapType::kBottom: 23481cb0ef41Sopenharmony_ci UNREACHABLE(); 23491cb0ef41Sopenharmony_ci default: 23501cb0ef41Sopenharmony_ci // TODO(7748): Add support for custom struct/array types. 23511cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 23521cb0ef41Sopenharmony_ci } 23531cb0ef41Sopenharmony_ci break; 23541cb0ef41Sopenharmony_ci case i::wasm::kRtt: 23551cb0ef41Sopenharmony_ci case i::wasm::kI8: 23561cb0ef41Sopenharmony_ci case i::wasm::kI16: 23571cb0ef41Sopenharmony_ci case i::wasm::kVoid: 23581cb0ef41Sopenharmony_ci case i::wasm::kBottom: 23591cb0ef41Sopenharmony_ci case i::wasm::kS128: 23601cb0ef41Sopenharmony_ci UNREACHABLE(); 23611cb0ef41Sopenharmony_ci } 23621cb0ef41Sopenharmony_ci args.GetReturnValue().Set(result); 23631cb0ef41Sopenharmony_ci} 23641cb0ef41Sopenharmony_ci 23651cb0ef41Sopenharmony_civoid WebAssemblyExceptionIs(const v8::FunctionCallbackInfo<v8::Value>& args) { 23661cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 23671cb0ef41Sopenharmony_ci HandleScope scope(isolate); 23681cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 23691cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception.is()"); 23701cb0ef41Sopenharmony_ci 23711cb0ef41Sopenharmony_ci EXTRACT_THIS(exception, WasmExceptionPackage); 23721cb0ef41Sopenharmony_ci if (thrower.error()) return; 23731cb0ef41Sopenharmony_ci 23741cb0ef41Sopenharmony_ci auto tag = i::WasmExceptionPackage::GetExceptionTag(i_isolate, exception); 23751cb0ef41Sopenharmony_ci if (tag->IsUndefined()) { 23761cb0ef41Sopenharmony_ci thrower.TypeError("Expected a WebAssembly.Exception object"); 23771cb0ef41Sopenharmony_ci return; 23781cb0ef41Sopenharmony_ci } 23791cb0ef41Sopenharmony_ci DCHECK(tag->IsWasmExceptionTag()); 23801cb0ef41Sopenharmony_ci 23811cb0ef41Sopenharmony_ci auto maybe_tag = GetFirstArgumentAsTag(args, &thrower); 23821cb0ef41Sopenharmony_ci if (thrower.error()) { 23831cb0ef41Sopenharmony_ci return; 23841cb0ef41Sopenharmony_ci } 23851cb0ef41Sopenharmony_ci auto tag_arg = maybe_tag.ToHandleChecked(); 23861cb0ef41Sopenharmony_ci args.GetReturnValue().Set(tag_arg->tag() == *tag); 23871cb0ef41Sopenharmony_ci} 23881cb0ef41Sopenharmony_ci 23891cb0ef41Sopenharmony_civoid WebAssemblyGlobalGetValueCommon( 23901cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) { 23911cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 23921cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 23931cb0ef41Sopenharmony_ci HandleScope scope(isolate); 23941cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, name); 23951cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmGlobalObject); 23961cb0ef41Sopenharmony_ci 23971cb0ef41Sopenharmony_ci v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 23981cb0ef41Sopenharmony_ci 23991cb0ef41Sopenharmony_ci switch (receiver->type().kind()) { 24001cb0ef41Sopenharmony_ci case i::wasm::kI32: 24011cb0ef41Sopenharmony_ci return_value.Set(receiver->GetI32()); 24021cb0ef41Sopenharmony_ci break; 24031cb0ef41Sopenharmony_ci case i::wasm::kI64: { 24041cb0ef41Sopenharmony_ci Local<BigInt> value = BigInt::New(isolate, receiver->GetI64()); 24051cb0ef41Sopenharmony_ci return_value.Set(value); 24061cb0ef41Sopenharmony_ci break; 24071cb0ef41Sopenharmony_ci } 24081cb0ef41Sopenharmony_ci case i::wasm::kF32: 24091cb0ef41Sopenharmony_ci return_value.Set(receiver->GetF32()); 24101cb0ef41Sopenharmony_ci break; 24111cb0ef41Sopenharmony_ci case i::wasm::kF64: 24121cb0ef41Sopenharmony_ci return_value.Set(receiver->GetF64()); 24131cb0ef41Sopenharmony_ci break; 24141cb0ef41Sopenharmony_ci case i::wasm::kS128: 24151cb0ef41Sopenharmony_ci thrower.TypeError("Can't get the value of s128 WebAssembly.Global"); 24161cb0ef41Sopenharmony_ci break; 24171cb0ef41Sopenharmony_ci case i::wasm::kRef: 24181cb0ef41Sopenharmony_ci case i::wasm::kOptRef: 24191cb0ef41Sopenharmony_ci switch (receiver->type().heap_representation()) { 24201cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: 24211cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(receiver->GetRef())); 24221cb0ef41Sopenharmony_ci break; 24231cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: { 24241cb0ef41Sopenharmony_ci i::Handle<i::Object> result = receiver->GetRef(); 24251cb0ef41Sopenharmony_ci if (result->IsWasmInternalFunction()) { 24261cb0ef41Sopenharmony_ci result = handle( 24271cb0ef41Sopenharmony_ci i::Handle<i::WasmInternalFunction>::cast(result)->external(), 24281cb0ef41Sopenharmony_ci i_isolate); 24291cb0ef41Sopenharmony_ci } 24301cb0ef41Sopenharmony_ci return_value.Set(Utils::ToLocal(result)); 24311cb0ef41Sopenharmony_ci break; 24321cb0ef41Sopenharmony_ci } 24331cb0ef41Sopenharmony_ci case i::wasm::HeapType::kBottom: 24341cb0ef41Sopenharmony_ci UNREACHABLE(); 24351cb0ef41Sopenharmony_ci case i::wasm::HeapType::kI31: 24361cb0ef41Sopenharmony_ci case i::wasm::HeapType::kData: 24371cb0ef41Sopenharmony_ci case i::wasm::HeapType::kArray: 24381cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 24391cb0ef41Sopenharmony_ci default: 24401cb0ef41Sopenharmony_ci // TODO(7748): Implement these. 24411cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 24421cb0ef41Sopenharmony_ci } 24431cb0ef41Sopenharmony_ci break; 24441cb0ef41Sopenharmony_ci case i::wasm::kRtt: 24451cb0ef41Sopenharmony_ci UNIMPLEMENTED(); // TODO(7748): Implement. 24461cb0ef41Sopenharmony_ci case i::wasm::kI8: 24471cb0ef41Sopenharmony_ci case i::wasm::kI16: 24481cb0ef41Sopenharmony_ci case i::wasm::kBottom: 24491cb0ef41Sopenharmony_ci case i::wasm::kVoid: 24501cb0ef41Sopenharmony_ci UNREACHABLE(); 24511cb0ef41Sopenharmony_ci } 24521cb0ef41Sopenharmony_ci} 24531cb0ef41Sopenharmony_ci 24541cb0ef41Sopenharmony_ci// WebAssembly.Global.valueOf() -> num 24551cb0ef41Sopenharmony_civoid WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) { 24561cb0ef41Sopenharmony_ci return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()"); 24571cb0ef41Sopenharmony_ci} 24581cb0ef41Sopenharmony_ci 24591cb0ef41Sopenharmony_ci// get WebAssembly.Global.value -> num 24601cb0ef41Sopenharmony_civoid WebAssemblyGlobalGetValue( 24611cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 24621cb0ef41Sopenharmony_ci return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value"); 24631cb0ef41Sopenharmony_ci} 24641cb0ef41Sopenharmony_ci 24651cb0ef41Sopenharmony_ci// set WebAssembly.Global.value(num) 24661cb0ef41Sopenharmony_civoid WebAssemblyGlobalSetValue( 24671cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 24681cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 24691cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 24701cb0ef41Sopenharmony_ci HandleScope scope(isolate); 24711cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 24721cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value"); 24731cb0ef41Sopenharmony_ci EXTRACT_THIS(receiver, WasmGlobalObject); 24741cb0ef41Sopenharmony_ci 24751cb0ef41Sopenharmony_ci if (!receiver->is_mutable()) { 24761cb0ef41Sopenharmony_ci thrower.TypeError("Can't set the value of an immutable global."); 24771cb0ef41Sopenharmony_ci return; 24781cb0ef41Sopenharmony_ci } 24791cb0ef41Sopenharmony_ci if (args.Length() == 0) { 24801cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 is required"); 24811cb0ef41Sopenharmony_ci return; 24821cb0ef41Sopenharmony_ci } 24831cb0ef41Sopenharmony_ci 24841cb0ef41Sopenharmony_ci switch (receiver->type().kind()) { 24851cb0ef41Sopenharmony_ci case i::wasm::kI32: { 24861cb0ef41Sopenharmony_ci int32_t i32_value = 0; 24871cb0ef41Sopenharmony_ci if (!args[0]->Int32Value(context).To(&i32_value)) return; 24881cb0ef41Sopenharmony_ci receiver->SetI32(i32_value); 24891cb0ef41Sopenharmony_ci break; 24901cb0ef41Sopenharmony_ci } 24911cb0ef41Sopenharmony_ci case i::wasm::kI64: { 24921cb0ef41Sopenharmony_ci v8::Local<v8::BigInt> bigint_value; 24931cb0ef41Sopenharmony_ci if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return; 24941cb0ef41Sopenharmony_ci receiver->SetI64(bigint_value->Int64Value()); 24951cb0ef41Sopenharmony_ci break; 24961cb0ef41Sopenharmony_ci } 24971cb0ef41Sopenharmony_ci case i::wasm::kF32: { 24981cb0ef41Sopenharmony_ci double f64_value = 0; 24991cb0ef41Sopenharmony_ci if (!args[0]->NumberValue(context).To(&f64_value)) return; 25001cb0ef41Sopenharmony_ci receiver->SetF32(i::DoubleToFloat32(f64_value)); 25011cb0ef41Sopenharmony_ci break; 25021cb0ef41Sopenharmony_ci } 25031cb0ef41Sopenharmony_ci case i::wasm::kF64: { 25041cb0ef41Sopenharmony_ci double f64_value = 0; 25051cb0ef41Sopenharmony_ci if (!args[0]->NumberValue(context).To(&f64_value)) return; 25061cb0ef41Sopenharmony_ci receiver->SetF64(f64_value); 25071cb0ef41Sopenharmony_ci break; 25081cb0ef41Sopenharmony_ci } 25091cb0ef41Sopenharmony_ci case i::wasm::kS128: 25101cb0ef41Sopenharmony_ci thrower.TypeError("Can't set the value of s128 WebAssembly.Global"); 25111cb0ef41Sopenharmony_ci break; 25121cb0ef41Sopenharmony_ci case i::wasm::kRef: 25131cb0ef41Sopenharmony_ci case i::wasm::kOptRef: 25141cb0ef41Sopenharmony_ci switch (receiver->type().heap_representation()) { 25151cb0ef41Sopenharmony_ci case i::wasm::HeapType::kAny: 25161cb0ef41Sopenharmony_ci receiver->SetExternRef(Utils::OpenHandle(*args[0])); 25171cb0ef41Sopenharmony_ci break; 25181cb0ef41Sopenharmony_ci case i::wasm::HeapType::kFunc: { 25191cb0ef41Sopenharmony_ci if (!receiver->SetFuncRef(i_isolate, Utils::OpenHandle(*args[0]))) { 25201cb0ef41Sopenharmony_ci thrower.TypeError( 25211cb0ef41Sopenharmony_ci "value of an funcref reference must be either null or an " 25221cb0ef41Sopenharmony_ci "exported function"); 25231cb0ef41Sopenharmony_ci } 25241cb0ef41Sopenharmony_ci break; 25251cb0ef41Sopenharmony_ci } 25261cb0ef41Sopenharmony_ci case i::wasm::HeapType::kBottom: 25271cb0ef41Sopenharmony_ci UNREACHABLE(); 25281cb0ef41Sopenharmony_ci case i::wasm::HeapType::kI31: 25291cb0ef41Sopenharmony_ci case i::wasm::HeapType::kData: 25301cb0ef41Sopenharmony_ci case i::wasm::HeapType::kArray: 25311cb0ef41Sopenharmony_ci case i::wasm::HeapType::kEq: 25321cb0ef41Sopenharmony_ci default: 25331cb0ef41Sopenharmony_ci // TODO(7748): Implement these. 25341cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 25351cb0ef41Sopenharmony_ci } 25361cb0ef41Sopenharmony_ci break; 25371cb0ef41Sopenharmony_ci case i::wasm::kRtt: 25381cb0ef41Sopenharmony_ci // TODO(7748): Implement. 25391cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 25401cb0ef41Sopenharmony_ci case i::wasm::kI8: 25411cb0ef41Sopenharmony_ci case i::wasm::kI16: 25421cb0ef41Sopenharmony_ci case i::wasm::kBottom: 25431cb0ef41Sopenharmony_ci case i::wasm::kVoid: 25441cb0ef41Sopenharmony_ci UNREACHABLE(); 25451cb0ef41Sopenharmony_ci } 25461cb0ef41Sopenharmony_ci} 25471cb0ef41Sopenharmony_ci 25481cb0ef41Sopenharmony_ci// WebAssembly.Global.type() -> GlobalType 25491cb0ef41Sopenharmony_civoid WebAssemblyGlobalType(const v8::FunctionCallbackInfo<v8::Value>& args) { 25501cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 25511cb0ef41Sopenharmony_ci HandleScope scope(isolate); 25521cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 25531cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()"); 25541cb0ef41Sopenharmony_ci 25551cb0ef41Sopenharmony_ci EXTRACT_THIS(global, WasmGlobalObject); 25561cb0ef41Sopenharmony_ci auto type = i::wasm::GetTypeForGlobal(i_isolate, global->is_mutable(), 25571cb0ef41Sopenharmony_ci global->type()); 25581cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(type)); 25591cb0ef41Sopenharmony_ci} 25601cb0ef41Sopenharmony_ci 25611cb0ef41Sopenharmony_ci// WebAssembly.Suspender.returnPromiseOnSuspend(WebAssembly.Function) -> 25621cb0ef41Sopenharmony_ci// WebAssembly.Function 25631cb0ef41Sopenharmony_civoid WebAssemblySuspenderReturnPromiseOnSuspend( 25641cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 25651cb0ef41Sopenharmony_ci Isolate* isolate = args.GetIsolate(); 25661cb0ef41Sopenharmony_ci HandleScope scope(isolate); 25671cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 25681cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower( 25691cb0ef41Sopenharmony_ci i_isolate, "WebAssembly.Suspender.returnPromiseOnSuspend()"); 25701cb0ef41Sopenharmony_ci if (args.Length() == 0) { 25711cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 is required"); 25721cb0ef41Sopenharmony_ci return; 25731cb0ef41Sopenharmony_ci } 25741cb0ef41Sopenharmony_ci auto maybe_function = GetFirstArgumentAsJSFunction(args, &thrower); 25751cb0ef41Sopenharmony_ci if (thrower.error()) return; 25761cb0ef41Sopenharmony_ci i::Handle<i::JSFunction> function = maybe_function.ToHandleChecked(); 25771cb0ef41Sopenharmony_ci i::SharedFunctionInfo sfi = function->shared(); 25781cb0ef41Sopenharmony_ci if (!sfi.HasWasmExportedFunctionData()) { 25791cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a wasm function"); 25801cb0ef41Sopenharmony_ci } 25811cb0ef41Sopenharmony_ci i::WasmExportedFunctionData data = sfi.wasm_exported_function_data(); 25821cb0ef41Sopenharmony_ci if (data.sig()->return_count() != 1) { 25831cb0ef41Sopenharmony_ci thrower.TypeError( 25841cb0ef41Sopenharmony_ci "Expected a WebAssembly.Function with exactly one return type"); 25851cb0ef41Sopenharmony_ci } 25861cb0ef41Sopenharmony_ci int index = data.function_index(); 25871cb0ef41Sopenharmony_ci i::Handle<i::WasmInstanceObject> instance( 25881cb0ef41Sopenharmony_ci i::WasmInstanceObject::cast(data.internal().ref()), i_isolate); 25891cb0ef41Sopenharmony_ci i::Handle<i::CodeT> wrapper = 25901cb0ef41Sopenharmony_ci BUILTIN_CODE(i_isolate, WasmReturnPromiseOnSuspend); 25911cb0ef41Sopenharmony_ci // Upcast to JSFunction to re-use the existing ToLocal helper below. 25921cb0ef41Sopenharmony_ci i::Handle<i::JSFunction> result = 25931cb0ef41Sopenharmony_ci i::Handle<i::WasmExternalFunction>::cast(i::WasmExportedFunction::New( 25941cb0ef41Sopenharmony_ci i_isolate, instance, index, 25951cb0ef41Sopenharmony_ci static_cast<int>(data.sig()->parameter_count()), wrapper)); 25961cb0ef41Sopenharmony_ci EXTRACT_THIS(suspender, WasmSuspenderObject); 25971cb0ef41Sopenharmony_ci auto function_data = i::WasmExportedFunctionData::cast( 25981cb0ef41Sopenharmony_ci result->shared().function_data(kAcquireLoad)); 25991cb0ef41Sopenharmony_ci function_data.set_suspender(*suspender); 26001cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(result)); 26011cb0ef41Sopenharmony_ci} 26021cb0ef41Sopenharmony_ci 26031cb0ef41Sopenharmony_ci// WebAssembly.Suspender.suspendOnReturnedPromise(Function) -> Function 26041cb0ef41Sopenharmony_civoid WebAssemblySuspenderSuspendOnReturnedPromise( 26051cb0ef41Sopenharmony_ci const v8::FunctionCallbackInfo<v8::Value>& args) { 26061cb0ef41Sopenharmony_ci v8::Isolate* isolate = args.GetIsolate(); 26071cb0ef41Sopenharmony_ci i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 26081cb0ef41Sopenharmony_ci HandleScope scope(isolate); 26091cb0ef41Sopenharmony_ci ScheduledErrorThrower thrower( 26101cb0ef41Sopenharmony_ci i_isolate, "WebAssembly.Suspender.suspendOnReturnedPromise()"); 26111cb0ef41Sopenharmony_ci if (!args[0]->IsObject()) { 26121cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a WebAssembly.Function"); 26131cb0ef41Sopenharmony_ci return; 26141cb0ef41Sopenharmony_ci } 26151cb0ef41Sopenharmony_ci i::Zone zone(i_isolate->allocator(), ZONE_NAME); 26161cb0ef41Sopenharmony_ci const i::wasm::FunctionSig* sig; 26171cb0ef41Sopenharmony_ci i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); 26181cb0ef41Sopenharmony_ci 26191cb0ef41Sopenharmony_ci if (i::WasmExportedFunction::IsWasmExportedFunction(*arg0)) { 26201cb0ef41Sopenharmony_ci // TODO(thibaudm): Suspend on wrapped wasm-to-wasm calls too. 26211cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 26221cb0ef41Sopenharmony_ci } else if (!i::WasmJSFunction::IsWasmJSFunction(*arg0)) { 26231cb0ef41Sopenharmony_ci thrower.TypeError("Argument 0 must be a WebAssembly.Function"); 26241cb0ef41Sopenharmony_ci return; 26251cb0ef41Sopenharmony_ci } 26261cb0ef41Sopenharmony_ci sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone); 26271cb0ef41Sopenharmony_ci if (sig->return_count() != 1 || sig->GetReturn(0) != i::wasm::kWasmAnyRef) { 26281cb0ef41Sopenharmony_ci thrower.TypeError("Expected a WebAssembly.Function with return type %s", 26291cb0ef41Sopenharmony_ci i::wasm::kWasmAnyRef.name().c_str()); 26301cb0ef41Sopenharmony_ci } 26311cb0ef41Sopenharmony_ci 26321cb0ef41Sopenharmony_ci auto callable = handle( 26331cb0ef41Sopenharmony_ci i::Handle<i::WasmJSFunction>::cast(arg0)->GetCallable(), i_isolate); 26341cb0ef41Sopenharmony_ci EXTRACT_THIS(suspender, WasmSuspenderObject); 26351cb0ef41Sopenharmony_ci i::Handle<i::JSFunction> result = 26361cb0ef41Sopenharmony_ci i::WasmJSFunction::New(i_isolate, sig, callable, suspender); 26371cb0ef41Sopenharmony_ci args.GetReturnValue().Set(Utils::ToLocal(result)); 26381cb0ef41Sopenharmony_ci} 26391cb0ef41Sopenharmony_ci} // namespace 26401cb0ef41Sopenharmony_ci 26411cb0ef41Sopenharmony_ci// TODO(titzer): we use the API to create the function template because the 26421cb0ef41Sopenharmony_ci// internal guts are too ugly to replicate here. 26431cb0ef41Sopenharmony_cistatic i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate( 26441cb0ef41Sopenharmony_ci i::Isolate* i_isolate, FunctionCallback func, bool has_prototype, 26451cb0ef41Sopenharmony_ci SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { 26461cb0ef41Sopenharmony_ci Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); 26471cb0ef41Sopenharmony_ci ConstructorBehavior behavior = 26481cb0ef41Sopenharmony_ci has_prototype ? ConstructorBehavior::kAllow : ConstructorBehavior::kThrow; 26491cb0ef41Sopenharmony_ci Local<FunctionTemplate> templ = FunctionTemplate::New( 26501cb0ef41Sopenharmony_ci isolate, func, {}, {}, 0, behavior, side_effect_type); 26511cb0ef41Sopenharmony_ci if (has_prototype) templ->ReadOnlyPrototype(); 26521cb0ef41Sopenharmony_ci return v8::Utils::OpenHandle(*templ); 26531cb0ef41Sopenharmony_ci} 26541cb0ef41Sopenharmony_ci 26551cb0ef41Sopenharmony_cistatic i::Handle<i::ObjectTemplateInfo> NewObjectTemplate( 26561cb0ef41Sopenharmony_ci i::Isolate* i_isolate) { 26571cb0ef41Sopenharmony_ci Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); 26581cb0ef41Sopenharmony_ci Local<ObjectTemplate> templ = ObjectTemplate::New(isolate); 26591cb0ef41Sopenharmony_ci return v8::Utils::OpenHandle(*templ); 26601cb0ef41Sopenharmony_ci} 26611cb0ef41Sopenharmony_ci 26621cb0ef41Sopenharmony_cinamespace internal { 26631cb0ef41Sopenharmony_ci 26641cb0ef41Sopenharmony_ciHandle<JSFunction> CreateFunc( 26651cb0ef41Sopenharmony_ci Isolate* isolate, Handle<String> name, FunctionCallback func, 26661cb0ef41Sopenharmony_ci bool has_prototype, 26671cb0ef41Sopenharmony_ci SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { 26681cb0ef41Sopenharmony_ci Handle<FunctionTemplateInfo> temp = 26691cb0ef41Sopenharmony_ci NewFunctionTemplate(isolate, func, has_prototype, side_effect_type); 26701cb0ef41Sopenharmony_ci Handle<JSFunction> function = 26711cb0ef41Sopenharmony_ci ApiNatives::InstantiateFunction(temp, name).ToHandleChecked(); 26721cb0ef41Sopenharmony_ci DCHECK(function->shared().HasSharedName()); 26731cb0ef41Sopenharmony_ci return function; 26741cb0ef41Sopenharmony_ci} 26751cb0ef41Sopenharmony_ci 26761cb0ef41Sopenharmony_ciHandle<JSFunction> InstallFunc( 26771cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSObject> object, const char* str, 26781cb0ef41Sopenharmony_ci FunctionCallback func, int length, bool has_prototype = false, 26791cb0ef41Sopenharmony_ci PropertyAttributes attributes = NONE, 26801cb0ef41Sopenharmony_ci SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { 26811cb0ef41Sopenharmony_ci Handle<String> name = v8_str(isolate, str); 26821cb0ef41Sopenharmony_ci Handle<JSFunction> function = 26831cb0ef41Sopenharmony_ci CreateFunc(isolate, name, func, has_prototype, side_effect_type); 26841cb0ef41Sopenharmony_ci function->shared().set_length(length); 26851cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, object, name, function, attributes); 26861cb0ef41Sopenharmony_ci return function; 26871cb0ef41Sopenharmony_ci} 26881cb0ef41Sopenharmony_ci 26891cb0ef41Sopenharmony_ciHandle<JSFunction> InstallConstructorFunc(Isolate* isolate, 26901cb0ef41Sopenharmony_ci Handle<JSObject> object, 26911cb0ef41Sopenharmony_ci const char* str, 26921cb0ef41Sopenharmony_ci FunctionCallback func) { 26931cb0ef41Sopenharmony_ci return InstallFunc(isolate, object, str, func, 1, true, DONT_ENUM, 26941cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 26951cb0ef41Sopenharmony_ci} 26961cb0ef41Sopenharmony_ci 26971cb0ef41Sopenharmony_ciHandle<String> GetterName(Isolate* isolate, Handle<String> name) { 26981cb0ef41Sopenharmony_ci return Name::ToFunctionName(isolate, name, isolate->factory()->get_string()) 26991cb0ef41Sopenharmony_ci .ToHandleChecked(); 27001cb0ef41Sopenharmony_ci} 27011cb0ef41Sopenharmony_ci 27021cb0ef41Sopenharmony_civoid InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str, 27031cb0ef41Sopenharmony_ci FunctionCallback func) { 27041cb0ef41Sopenharmony_ci Handle<String> name = v8_str(isolate, str); 27051cb0ef41Sopenharmony_ci Handle<JSFunction> function = 27061cb0ef41Sopenharmony_ci CreateFunc(isolate, GetterName(isolate, name), func, false, 27071cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 27081cb0ef41Sopenharmony_ci 27091cb0ef41Sopenharmony_ci Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name), 27101cb0ef41Sopenharmony_ci Utils::ToLocal(function), 27111cb0ef41Sopenharmony_ci Local<Function>(), v8::None); 27121cb0ef41Sopenharmony_ci} 27131cb0ef41Sopenharmony_ci 27141cb0ef41Sopenharmony_ciHandle<String> SetterName(Isolate* isolate, Handle<String> name) { 27151cb0ef41Sopenharmony_ci return Name::ToFunctionName(isolate, name, isolate->factory()->set_string()) 27161cb0ef41Sopenharmony_ci .ToHandleChecked(); 27171cb0ef41Sopenharmony_ci} 27181cb0ef41Sopenharmony_ci 27191cb0ef41Sopenharmony_civoid InstallGetterSetter(Isolate* isolate, Handle<JSObject> object, 27201cb0ef41Sopenharmony_ci const char* str, FunctionCallback getter, 27211cb0ef41Sopenharmony_ci FunctionCallback setter) { 27221cb0ef41Sopenharmony_ci Handle<String> name = v8_str(isolate, str); 27231cb0ef41Sopenharmony_ci Handle<JSFunction> getter_func = 27241cb0ef41Sopenharmony_ci CreateFunc(isolate, GetterName(isolate, name), getter, false, 27251cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 27261cb0ef41Sopenharmony_ci Handle<JSFunction> setter_func = 27271cb0ef41Sopenharmony_ci CreateFunc(isolate, SetterName(isolate, name), setter, false); 27281cb0ef41Sopenharmony_ci setter_func->shared().set_length(1); 27291cb0ef41Sopenharmony_ci 27301cb0ef41Sopenharmony_ci Utils::ToLocal(object)->SetAccessorProperty( 27311cb0ef41Sopenharmony_ci Utils::ToLocal(name), Utils::ToLocal(getter_func), 27321cb0ef41Sopenharmony_ci Utils::ToLocal(setter_func), v8::None); 27331cb0ef41Sopenharmony_ci} 27341cb0ef41Sopenharmony_ci 27351cb0ef41Sopenharmony_ci// Assigns a dummy instance template to the given constructor function. Used to 27361cb0ef41Sopenharmony_ci// make sure the implicit receivers for the constructors in this file have an 27371cb0ef41Sopenharmony_ci// instance type different from the internal one, they allocate the resulting 27381cb0ef41Sopenharmony_ci// object explicitly and ignore implicit receiver. 27391cb0ef41Sopenharmony_civoid SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) { 27401cb0ef41Sopenharmony_ci Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate); 27411cb0ef41Sopenharmony_ci FunctionTemplateInfo::SetInstanceTemplate( 27421cb0ef41Sopenharmony_ci isolate, handle(fun->shared().get_api_func_data(), isolate), 27431cb0ef41Sopenharmony_ci instance_template); 27441cb0ef41Sopenharmony_ci} 27451cb0ef41Sopenharmony_ci 27461cb0ef41Sopenharmony_ciHandle<JSObject> SetupConstructor(Isolate* isolate, 27471cb0ef41Sopenharmony_ci Handle<JSFunction> constructor, 27481cb0ef41Sopenharmony_ci InstanceType instance_type, int instance_size, 27491cb0ef41Sopenharmony_ci const char* name = nullptr) { 27501cb0ef41Sopenharmony_ci SetDummyInstanceTemplate(isolate, constructor); 27511cb0ef41Sopenharmony_ci JSFunction::EnsureHasInitialMap(constructor); 27521cb0ef41Sopenharmony_ci Handle<JSObject> proto(JSObject::cast(constructor->instance_prototype()), 27531cb0ef41Sopenharmony_ci isolate); 27541cb0ef41Sopenharmony_ci Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size); 27551cb0ef41Sopenharmony_ci JSFunction::SetInitialMap(isolate, constructor, map, proto); 27561cb0ef41Sopenharmony_ci constexpr PropertyAttributes ro_attributes = 27571cb0ef41Sopenharmony_ci static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY); 27581cb0ef41Sopenharmony_ci if (name) { 27591cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, proto, 27601cb0ef41Sopenharmony_ci isolate->factory()->to_string_tag_symbol(), 27611cb0ef41Sopenharmony_ci v8_str(isolate, name), ro_attributes); 27621cb0ef41Sopenharmony_ci } 27631cb0ef41Sopenharmony_ci return proto; 27641cb0ef41Sopenharmony_ci} 27651cb0ef41Sopenharmony_ci 27661cb0ef41Sopenharmony_ci// static 27671cb0ef41Sopenharmony_civoid WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) { 27681cb0ef41Sopenharmony_ci Handle<JSGlobalObject> global = isolate->global_object(); 27691cb0ef41Sopenharmony_ci Handle<Context> context(global->native_context(), isolate); 27701cb0ef41Sopenharmony_ci // Install the JS API once only. 27711cb0ef41Sopenharmony_ci Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX); 27721cb0ef41Sopenharmony_ci if (!prev.IsUndefined(isolate)) { 27731cb0ef41Sopenharmony_ci DCHECK(prev.IsJSFunction()); 27741cb0ef41Sopenharmony_ci return; 27751cb0ef41Sopenharmony_ci } 27761cb0ef41Sopenharmony_ci 27771cb0ef41Sopenharmony_ci Factory* factory = isolate->factory(); 27781cb0ef41Sopenharmony_ci 27791cb0ef41Sopenharmony_ci // Setup WebAssembly 27801cb0ef41Sopenharmony_ci Handle<String> name = v8_str(isolate, "WebAssembly"); 27811cb0ef41Sopenharmony_ci // Not supposed to be called, hence using the kIllegal builtin as code. 27821cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> info = 27831cb0ef41Sopenharmony_ci factory->NewSharedFunctionInfoForBuiltin(name, Builtin::kIllegal); 27841cb0ef41Sopenharmony_ci info->set_language_mode(LanguageMode::kStrict); 27851cb0ef41Sopenharmony_ci 27861cb0ef41Sopenharmony_ci Handle<JSFunction> cons = 27871cb0ef41Sopenharmony_ci Factory::JSFunctionBuilder{isolate, info, context}.Build(); 27881cb0ef41Sopenharmony_ci JSFunction::SetPrototype(cons, isolate->initial_object_prototype()); 27891cb0ef41Sopenharmony_ci Handle<JSObject> webassembly = 27901cb0ef41Sopenharmony_ci factory->NewJSObject(cons, AllocationType::kOld); 27911cb0ef41Sopenharmony_ci 27921cb0ef41Sopenharmony_ci PropertyAttributes ro_attributes = 27931cb0ef41Sopenharmony_ci static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY); 27941cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(), 27951cb0ef41Sopenharmony_ci name, ro_attributes); 27961cb0ef41Sopenharmony_ci InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1); 27971cb0ef41Sopenharmony_ci InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1); 27981cb0ef41Sopenharmony_ci InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1); 27991cb0ef41Sopenharmony_ci 28001cb0ef41Sopenharmony_ci if (FLAG_wasm_test_streaming) { 28011cb0ef41Sopenharmony_ci isolate->set_wasm_streaming_callback(WasmStreamingCallbackForTesting); 28021cb0ef41Sopenharmony_ci } 28031cb0ef41Sopenharmony_ci 28041cb0ef41Sopenharmony_ci if (isolate->wasm_streaming_callback() != nullptr) { 28051cb0ef41Sopenharmony_ci InstallFunc(isolate, webassembly, "compileStreaming", 28061cb0ef41Sopenharmony_ci WebAssemblyCompileStreaming, 1); 28071cb0ef41Sopenharmony_ci InstallFunc(isolate, webassembly, "instantiateStreaming", 28081cb0ef41Sopenharmony_ci WebAssemblyInstantiateStreaming, 1); 28091cb0ef41Sopenharmony_ci } 28101cb0ef41Sopenharmony_ci 28111cb0ef41Sopenharmony_ci // Expose the API on the global object if configured to do so. 28121cb0ef41Sopenharmony_ci if (exposed_on_global_object) { 28131cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM); 28141cb0ef41Sopenharmony_ci } 28151cb0ef41Sopenharmony_ci 28161cb0ef41Sopenharmony_ci // Setup Module 28171cb0ef41Sopenharmony_ci Handle<JSFunction> module_constructor = 28181cb0ef41Sopenharmony_ci InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule); 28191cb0ef41Sopenharmony_ci SetupConstructor(isolate, module_constructor, i::WASM_MODULE_OBJECT_TYPE, 28201cb0ef41Sopenharmony_ci WasmModuleObject::kHeaderSize, "WebAssembly.Module"); 28211cb0ef41Sopenharmony_ci context->set_wasm_module_constructor(*module_constructor); 28221cb0ef41Sopenharmony_ci InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports, 28231cb0ef41Sopenharmony_ci 1, false, NONE, SideEffectType::kHasNoSideEffect); 28241cb0ef41Sopenharmony_ci InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports, 28251cb0ef41Sopenharmony_ci 1, false, NONE, SideEffectType::kHasNoSideEffect); 28261cb0ef41Sopenharmony_ci InstallFunc(isolate, module_constructor, "customSections", 28271cb0ef41Sopenharmony_ci WebAssemblyModuleCustomSections, 2, false, NONE, 28281cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 28291cb0ef41Sopenharmony_ci 28301cb0ef41Sopenharmony_ci // Setup Instance 28311cb0ef41Sopenharmony_ci Handle<JSFunction> instance_constructor = InstallConstructorFunc( 28321cb0ef41Sopenharmony_ci isolate, webassembly, "Instance", WebAssemblyInstance); 28331cb0ef41Sopenharmony_ci Handle<JSObject> instance_proto = SetupConstructor( 28341cb0ef41Sopenharmony_ci isolate, instance_constructor, i::WASM_INSTANCE_OBJECT_TYPE, 28351cb0ef41Sopenharmony_ci WasmInstanceObject::kHeaderSize, "WebAssembly.Instance"); 28361cb0ef41Sopenharmony_ci context->set_wasm_instance_constructor(*instance_constructor); 28371cb0ef41Sopenharmony_ci InstallGetter(isolate, instance_proto, "exports", 28381cb0ef41Sopenharmony_ci WebAssemblyInstanceGetExports); 28391cb0ef41Sopenharmony_ci 28401cb0ef41Sopenharmony_ci // The context is not set up completely yet. That's why we cannot use 28411cb0ef41Sopenharmony_ci // {WasmFeatures::FromIsolate} and have to use {WasmFeatures::FromFlags} 28421cb0ef41Sopenharmony_ci // instead. 28431cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromFlags(); 28441cb0ef41Sopenharmony_ci 28451cb0ef41Sopenharmony_ci // Setup Table 28461cb0ef41Sopenharmony_ci Handle<JSFunction> table_constructor = 28471cb0ef41Sopenharmony_ci InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable); 28481cb0ef41Sopenharmony_ci Handle<JSObject> table_proto = 28491cb0ef41Sopenharmony_ci SetupConstructor(isolate, table_constructor, i::WASM_TABLE_OBJECT_TYPE, 28501cb0ef41Sopenharmony_ci WasmTableObject::kHeaderSize, "WebAssembly.Table"); 28511cb0ef41Sopenharmony_ci context->set_wasm_table_constructor(*table_constructor); 28521cb0ef41Sopenharmony_ci InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength); 28531cb0ef41Sopenharmony_ci InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1); 28541cb0ef41Sopenharmony_ci InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1, false, NONE, 28551cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 28561cb0ef41Sopenharmony_ci InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2); 28571cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 28581cb0ef41Sopenharmony_ci InstallFunc(isolate, table_proto, "type", WebAssemblyTableType, 0, false, 28591cb0ef41Sopenharmony_ci NONE, SideEffectType::kHasNoSideEffect); 28601cb0ef41Sopenharmony_ci } 28611cb0ef41Sopenharmony_ci 28621cb0ef41Sopenharmony_ci // Setup Memory 28631cb0ef41Sopenharmony_ci Handle<JSFunction> memory_constructor = 28641cb0ef41Sopenharmony_ci InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory); 28651cb0ef41Sopenharmony_ci Handle<JSObject> memory_proto = 28661cb0ef41Sopenharmony_ci SetupConstructor(isolate, memory_constructor, i::WASM_MEMORY_OBJECT_TYPE, 28671cb0ef41Sopenharmony_ci WasmMemoryObject::kHeaderSize, "WebAssembly.Memory"); 28681cb0ef41Sopenharmony_ci context->set_wasm_memory_constructor(*memory_constructor); 28691cb0ef41Sopenharmony_ci InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1); 28701cb0ef41Sopenharmony_ci InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer); 28711cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 28721cb0ef41Sopenharmony_ci InstallFunc(isolate, memory_proto, "type", WebAssemblyMemoryType, 0, false, 28731cb0ef41Sopenharmony_ci NONE, SideEffectType::kHasNoSideEffect); 28741cb0ef41Sopenharmony_ci } 28751cb0ef41Sopenharmony_ci 28761cb0ef41Sopenharmony_ci // Setup Global 28771cb0ef41Sopenharmony_ci Handle<JSFunction> global_constructor = 28781cb0ef41Sopenharmony_ci InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal); 28791cb0ef41Sopenharmony_ci Handle<JSObject> global_proto = 28801cb0ef41Sopenharmony_ci SetupConstructor(isolate, global_constructor, i::WASM_GLOBAL_OBJECT_TYPE, 28811cb0ef41Sopenharmony_ci WasmGlobalObject::kHeaderSize, "WebAssembly.Global"); 28821cb0ef41Sopenharmony_ci context->set_wasm_global_constructor(*global_constructor); 28831cb0ef41Sopenharmony_ci InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0, 28841cb0ef41Sopenharmony_ci false, NONE, SideEffectType::kHasNoSideEffect); 28851cb0ef41Sopenharmony_ci InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue, 28861cb0ef41Sopenharmony_ci WebAssemblyGlobalSetValue); 28871cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 28881cb0ef41Sopenharmony_ci InstallFunc(isolate, global_proto, "type", WebAssemblyGlobalType, 0, false, 28891cb0ef41Sopenharmony_ci NONE, SideEffectType::kHasNoSideEffect); 28901cb0ef41Sopenharmony_ci } 28911cb0ef41Sopenharmony_ci 28921cb0ef41Sopenharmony_ci // Setup Exception 28931cb0ef41Sopenharmony_ci if (enabled_features.has_eh()) { 28941cb0ef41Sopenharmony_ci Handle<JSFunction> tag_constructor = 28951cb0ef41Sopenharmony_ci InstallConstructorFunc(isolate, webassembly, "Tag", WebAssemblyTag); 28961cb0ef41Sopenharmony_ci Handle<JSObject> tag_proto = 28971cb0ef41Sopenharmony_ci SetupConstructor(isolate, tag_constructor, i::WASM_TAG_OBJECT_TYPE, 28981cb0ef41Sopenharmony_ci WasmTagObject::kHeaderSize, "WebAssembly.Tag"); 28991cb0ef41Sopenharmony_ci context->set_wasm_tag_constructor(*tag_constructor); 29001cb0ef41Sopenharmony_ci 29011cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 29021cb0ef41Sopenharmony_ci InstallFunc(isolate, tag_proto, "type", WebAssemblyTagType, 0); 29031cb0ef41Sopenharmony_ci } 29041cb0ef41Sopenharmony_ci // Set up runtime exception constructor. 29051cb0ef41Sopenharmony_ci Handle<JSFunction> exception_constructor = InstallConstructorFunc( 29061cb0ef41Sopenharmony_ci isolate, webassembly, "Exception", WebAssemblyException); 29071cb0ef41Sopenharmony_ci SetDummyInstanceTemplate(isolate, exception_constructor); 29081cb0ef41Sopenharmony_ci Handle<Map> exception_map(isolate->native_context() 29091cb0ef41Sopenharmony_ci ->wasm_exception_error_function() 29101cb0ef41Sopenharmony_ci .initial_map(), 29111cb0ef41Sopenharmony_ci isolate); 29121cb0ef41Sopenharmony_ci Handle<JSObject> exception_proto( 29131cb0ef41Sopenharmony_ci JSObject::cast(isolate->native_context() 29141cb0ef41Sopenharmony_ci ->wasm_exception_error_function() 29151cb0ef41Sopenharmony_ci .instance_prototype()), 29161cb0ef41Sopenharmony_ci isolate); 29171cb0ef41Sopenharmony_ci InstallFunc(isolate, exception_proto, "getArg", WebAssemblyExceptionGetArg, 29181cb0ef41Sopenharmony_ci 2); 29191cb0ef41Sopenharmony_ci InstallFunc(isolate, exception_proto, "is", WebAssemblyExceptionIs, 1); 29201cb0ef41Sopenharmony_ci context->set_wasm_exception_constructor(*exception_constructor); 29211cb0ef41Sopenharmony_ci JSFunction::SetInitialMap(isolate, exception_constructor, exception_map, 29221cb0ef41Sopenharmony_ci exception_proto); 29231cb0ef41Sopenharmony_ci } 29241cb0ef41Sopenharmony_ci 29251cb0ef41Sopenharmony_ci // Setup Suspender. 29261cb0ef41Sopenharmony_ci if (enabled_features.has_stack_switching()) { 29271cb0ef41Sopenharmony_ci Handle<JSFunction> suspender_constructor = InstallConstructorFunc( 29281cb0ef41Sopenharmony_ci isolate, webassembly, "Suspender", WebAssemblySuspender); 29291cb0ef41Sopenharmony_ci context->set_wasm_suspender_constructor(*suspender_constructor); 29301cb0ef41Sopenharmony_ci Handle<JSObject> suspender_proto = SetupConstructor( 29311cb0ef41Sopenharmony_ci isolate, suspender_constructor, i::WASM_SUSPENDER_OBJECT_TYPE, 29321cb0ef41Sopenharmony_ci WasmSuspenderObject::kHeaderSize, "WebAssembly.Suspender"); 29331cb0ef41Sopenharmony_ci InstallFunc(isolate, suspender_proto, "returnPromiseOnSuspend", 29341cb0ef41Sopenharmony_ci WebAssemblySuspenderReturnPromiseOnSuspend, 1); 29351cb0ef41Sopenharmony_ci InstallFunc(isolate, suspender_proto, "suspendOnReturnedPromise", 29361cb0ef41Sopenharmony_ci WebAssemblySuspenderSuspendOnReturnedPromise, 1); 29371cb0ef41Sopenharmony_ci } 29381cb0ef41Sopenharmony_ci 29391cb0ef41Sopenharmony_ci // Setup Function 29401cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 29411cb0ef41Sopenharmony_ci Handle<JSFunction> function_constructor = InstallConstructorFunc( 29421cb0ef41Sopenharmony_ci isolate, webassembly, "Function", WebAssemblyFunction); 29431cb0ef41Sopenharmony_ci SetDummyInstanceTemplate(isolate, function_constructor); 29441cb0ef41Sopenharmony_ci JSFunction::EnsureHasInitialMap(function_constructor); 29451cb0ef41Sopenharmony_ci Handle<JSObject> function_proto( 29461cb0ef41Sopenharmony_ci JSObject::cast(function_constructor->instance_prototype()), isolate); 29471cb0ef41Sopenharmony_ci Handle<Map> function_map = isolate->factory()->CreateSloppyFunctionMap( 29481cb0ef41Sopenharmony_ci FUNCTION_WITHOUT_PROTOTYPE, MaybeHandle<JSFunction>()); 29491cb0ef41Sopenharmony_ci CHECK(JSObject::SetPrototype( 29501cb0ef41Sopenharmony_ci isolate, function_proto, 29511cb0ef41Sopenharmony_ci handle(context->function_function().prototype(), isolate), false, 29521cb0ef41Sopenharmony_ci kDontThrow) 29531cb0ef41Sopenharmony_ci .FromJust()); 29541cb0ef41Sopenharmony_ci JSFunction::SetInitialMap(isolate, function_constructor, function_map, 29551cb0ef41Sopenharmony_ci function_proto); 29561cb0ef41Sopenharmony_ci InstallFunc(isolate, function_constructor, "type", WebAssemblyFunctionType, 29571cb0ef41Sopenharmony_ci 1); 29581cb0ef41Sopenharmony_ci // Make all exported functions an instance of {WebAssembly.Function}. 29591cb0ef41Sopenharmony_ci context->set_wasm_exported_function_map(*function_map); 29601cb0ef41Sopenharmony_ci } else { 29611cb0ef41Sopenharmony_ci // Make all exported functions an instance of {Function}. 29621cb0ef41Sopenharmony_ci Handle<Map> function_map = isolate->sloppy_function_without_prototype_map(); 29631cb0ef41Sopenharmony_ci context->set_wasm_exported_function_map(*function_map); 29641cb0ef41Sopenharmony_ci } 29651cb0ef41Sopenharmony_ci 29661cb0ef41Sopenharmony_ci // Setup errors 29671cb0ef41Sopenharmony_ci Handle<JSFunction> compile_error( 29681cb0ef41Sopenharmony_ci isolate->native_context()->wasm_compile_error_function(), isolate); 29691cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, webassembly, 29701cb0ef41Sopenharmony_ci isolate->factory()->CompileError_string(), 29711cb0ef41Sopenharmony_ci compile_error, DONT_ENUM); 29721cb0ef41Sopenharmony_ci Handle<JSFunction> link_error( 29731cb0ef41Sopenharmony_ci isolate->native_context()->wasm_link_error_function(), isolate); 29741cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, webassembly, 29751cb0ef41Sopenharmony_ci isolate->factory()->LinkError_string(), link_error, 29761cb0ef41Sopenharmony_ci DONT_ENUM); 29771cb0ef41Sopenharmony_ci Handle<JSFunction> runtime_error( 29781cb0ef41Sopenharmony_ci isolate->native_context()->wasm_runtime_error_function(), isolate); 29791cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, webassembly, 29801cb0ef41Sopenharmony_ci isolate->factory()->RuntimeError_string(), 29811cb0ef41Sopenharmony_ci runtime_error, DONT_ENUM); 29821cb0ef41Sopenharmony_ci} 29831cb0ef41Sopenharmony_ci 29841cb0ef41Sopenharmony_ci// static 29851cb0ef41Sopenharmony_civoid WasmJs::InstallConditionalFeatures(Isolate* isolate, 29861cb0ef41Sopenharmony_ci Handle<Context> context) { 29871cb0ef41Sopenharmony_ci // Exception handling may have been enabled by an origin trial. If so, make 29881cb0ef41Sopenharmony_ci // sure that the {WebAssembly.Tag} constructor is set up. 29891cb0ef41Sopenharmony_ci auto enabled_features = i::wasm::WasmFeatures::FromContext(isolate, context); 29901cb0ef41Sopenharmony_ci if (enabled_features.has_eh()) { 29911cb0ef41Sopenharmony_ci Handle<JSGlobalObject> global = handle(context->global_object(), isolate); 29921cb0ef41Sopenharmony_ci MaybeHandle<Object> maybe_webassembly = 29931cb0ef41Sopenharmony_ci JSObject::GetProperty(isolate, global, "WebAssembly"); 29941cb0ef41Sopenharmony_ci Handle<Object> webassembly_obj; 29951cb0ef41Sopenharmony_ci if (!maybe_webassembly.ToHandle(&webassembly_obj) || 29961cb0ef41Sopenharmony_ci !webassembly_obj->IsJSObject()) { 29971cb0ef41Sopenharmony_ci // There is no {WebAssembly} object, or it's not what we expect. 29981cb0ef41Sopenharmony_ci // Just return without adding the {Tag} constructor. 29991cb0ef41Sopenharmony_ci return; 30001cb0ef41Sopenharmony_ci } 30011cb0ef41Sopenharmony_ci Handle<JSObject> webassembly = Handle<JSObject>::cast(webassembly_obj); 30021cb0ef41Sopenharmony_ci // Setup Tag. 30031cb0ef41Sopenharmony_ci Handle<String> tag_name = v8_str(isolate, "Tag"); 30041cb0ef41Sopenharmony_ci // The {WebAssembly} object may already have been modified. The following 30051cb0ef41Sopenharmony_ci // code is designed to: 30061cb0ef41Sopenharmony_ci // - check for existing {Tag} properties on the object itself, and avoid 30071cb0ef41Sopenharmony_ci // overwriting them or adding duplicate properties 30081cb0ef41Sopenharmony_ci // - disregard any setters or read-only properties on the prototype chain 30091cb0ef41Sopenharmony_ci // - only make objects accessible to user code after all internal setup 30101cb0ef41Sopenharmony_ci // has been completed. 30111cb0ef41Sopenharmony_ci if (JSObject::HasOwnProperty(isolate, webassembly, tag_name) 30121cb0ef41Sopenharmony_ci .FromMaybe(true)) { 30131cb0ef41Sopenharmony_ci // Existing property, or exception. 30141cb0ef41Sopenharmony_ci return; 30151cb0ef41Sopenharmony_ci } 30161cb0ef41Sopenharmony_ci 30171cb0ef41Sopenharmony_ci bool has_prototype = true; 30181cb0ef41Sopenharmony_ci Handle<JSFunction> tag_constructor = 30191cb0ef41Sopenharmony_ci CreateFunc(isolate, tag_name, WebAssemblyTag, has_prototype, 30201cb0ef41Sopenharmony_ci SideEffectType::kHasNoSideEffect); 30211cb0ef41Sopenharmony_ci tag_constructor->shared().set_length(1); 30221cb0ef41Sopenharmony_ci context->set_wasm_tag_constructor(*tag_constructor); 30231cb0ef41Sopenharmony_ci Handle<JSObject> tag_proto = 30241cb0ef41Sopenharmony_ci SetupConstructor(isolate, tag_constructor, i::WASM_TAG_OBJECT_TYPE, 30251cb0ef41Sopenharmony_ci WasmTagObject::kHeaderSize, "WebAssembly.Tag"); 30261cb0ef41Sopenharmony_ci if (enabled_features.has_type_reflection()) { 30271cb0ef41Sopenharmony_ci InstallFunc(isolate, tag_proto, "type", WebAssemblyTagType, 0); 30281cb0ef41Sopenharmony_ci } 30291cb0ef41Sopenharmony_ci LookupIterator it(isolate, webassembly, tag_name, LookupIterator::OWN); 30301cb0ef41Sopenharmony_ci Maybe<bool> result = JSObject::DefineOwnPropertyIgnoreAttributes( 30311cb0ef41Sopenharmony_ci &it, tag_constructor, DONT_ENUM, Just(kDontThrow)); 30321cb0ef41Sopenharmony_ci // This could still fail if the object was non-extensible, but now we 30331cb0ef41Sopenharmony_ci // return anyway so there's no need to even check. 30341cb0ef41Sopenharmony_ci USE(result); 30351cb0ef41Sopenharmony_ci } 30361cb0ef41Sopenharmony_ci} 30371cb0ef41Sopenharmony_ci#undef ASSIGN 30381cb0ef41Sopenharmony_ci#undef EXTRACT_THIS 30391cb0ef41Sopenharmony_ci 30401cb0ef41Sopenharmony_ci} // namespace internal 30411cb0ef41Sopenharmony_ci} // namespace v8 3042