Revert "[wasm] Implement the new API for WebAssembly.instantiateStreaming"

This reverts commit b556c9eaa6.

Reason for revert: Flakes in layout tests: https://crbug.com/870187

Original change's description:
> [wasm] Implement the new API for WebAssembly.instantiateStreaming
> 
> This is the second V8 CL to refactor WebAssembly.instantiateStreaming to
> make it spec compliant again. The design doc where the whole change is
> discussed is available in the tracking bug. The tracking bug also
> references prototype implementations of the whole change, which includes
> the changes in this CL.
> 
> R=​mstarzinger@chromium.org
> 
> Bug: chromium:860637
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
> Change-Id: I776c0f24959ab5663727d3dfee0248a9b0642a42
> Reviewed-on: https://chromium-review.googlesource.com/1143187
> Commit-Queue: Andreas Haas <ahaas@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#54834}

TBR=mstarzinger@chromium.org,ahaas@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: chromium:860637
Change-Id: Icbf2603143068a49c61de162aa7185a753703e5d
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/1160261
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54872}
This commit is contained in:
Andreas Haas 2018-08-02 11:04:09 +02:00 committed by Commit Bot
parent 05c8d57a72
commit fea9300d9f
10 changed files with 139 additions and 294 deletions

View File

@ -7778,23 +7778,55 @@ class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
};
WasmModuleObjectBuilderStreaming::WasmModuleObjectBuilderStreaming(
Isolate* isolate) {
USE(isolate_);
Isolate* isolate)
: isolate_(isolate) {
MaybeLocal<Promise::Resolver> maybe_resolver =
Promise::Resolver::New(isolate->GetCurrentContext());
Local<Promise::Resolver> resolver = maybe_resolver.ToLocalChecked();
promise_.Reset(isolate, resolver->GetPromise());
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
i_isolate, handle(i_isolate->context(), i_isolate),
base::make_unique<AsyncCompilationResolver>(isolate, GetPromise()));
}
Local<Promise> WasmModuleObjectBuilderStreaming::GetPromise() { return {}; }
Local<Promise> WasmModuleObjectBuilderStreaming::GetPromise() {
return promise_.Get(isolate_);
}
void WasmModuleObjectBuilderStreaming::OnBytesReceived(const uint8_t* bytes,
size_t size) {
streaming_decoder_->OnBytesReceived(i::Vector<const uint8_t>(bytes, size));
}
void WasmModuleObjectBuilderStreaming::Finish() {
streaming_decoder_->Finish();
}
void WasmModuleObjectBuilderStreaming::Abort(MaybeLocal<Value> exception) {
Local<Promise> promise = GetPromise();
// The promise has already been resolved, e.g. because of a compilation
// error.
if (promise->State() != v8::Promise::kPending) return;
streaming_decoder_->Abort();
// If no exception value is provided, we do not reject the promise. This can
// happen when streaming compilation gets aborted when no script execution is
// allowed anymore, e.g. when a browser tab gets refreshed.
if (exception.IsEmpty()) return;
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
i::HandleScope scope(i_isolate);
Local<Context> context =
Utils::ToLocal(handle(i_isolate->context(), i_isolate));
auto maybe = resolver->Reject(context, exception.ToLocalChecked());
CHECK_IMPLIES(!maybe.FromMaybe(false), i_isolate->has_scheduled_exception());
}
WasmModuleObjectBuilderStreaming::~WasmModuleObjectBuilderStreaming() {
promise_.Reset();
}
// static

View File

@ -2095,7 +2095,7 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
AsyncCompileJob::AsyncCompileJob(
Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, size_t length,
Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver)
std::unique_ptr<CompilationResultResolver> resolver)
: isolate_(isolate),
async_counters_(isolate->async_counters()),
bytes_copy_(std::move(bytes_copy)),

View File

@ -79,7 +79,7 @@ class AsyncCompileJob {
public:
explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy,
size_t length, Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver);
std::unique_ptr<CompilationResultResolver> resolver);
~AsyncCompileJob();
void Start();
@ -139,14 +139,14 @@ class AsyncCompileJob {
Isolate* isolate_;
const std::shared_ptr<Counters> async_counters_;
// Copy of the module wire bytes, moved into the {native_module_} on its
// Copy of the module wire bytes, moved into the {native_module_} on it's
// creation.
std::unique_ptr<byte[]> bytes_copy_;
// Reference to the wire bytes (hold in {bytes_copy_} or as part of
// {native_module_}).
ModuleWireBytes wire_bytes_;
Handle<Context> native_context_;
std::shared_ptr<CompilationResultResolver> resolver_;
std::unique_ptr<CompilationResultResolver> resolver_;
std::shared_ptr<const WasmModule> module_;
std::vector<DeferredHandles*> deferred_handles_;

View File

@ -83,10 +83,7 @@ void StreamingDecoder::Finish() {
void StreamingDecoder::Abort() {
TRACE_STREAMING("Abort\n");
if (ok()) {
ok_ = false;
processor_->OnAbort();
}
if (ok()) processor_->OnAbort();
}
// An abstract class to share code among the states which decode VarInts. This

View File

@ -110,7 +110,7 @@ void WasmEngine::AsyncInstantiate(
}
void WasmEngine::AsyncCompile(
Isolate* isolate, std::shared_ptr<CompilationResultResolver> resolver,
Isolate* isolate, std::unique_ptr<CompilationResultResolver> resolver,
const ModuleWireBytes& bytes, bool is_shared) {
if (!FLAG_wasm_async_compilation) {
// Asynchronous compilation disabled; fall back on synchronous compilation.
@ -156,7 +156,7 @@ void WasmEngine::AsyncCompile(
std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
Isolate* isolate, Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver) {
std::unique_ptr<CompilationResultResolver> resolver) {
AsyncCompileJob* job =
CreateAsyncCompileJob(isolate, std::unique_ptr<byte[]>(nullptr), 0,
context, std::move(resolver));
@ -210,7 +210,7 @@ CodeTracer* WasmEngine::GetCodeTracer() {
AsyncCompileJob* WasmEngine::CreateAsyncCompileJob(
Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, size_t length,
Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver) {
std::unique_ptr<CompilationResultResolver> resolver) {
AsyncCompileJob* job = new AsyncCompileJob(
isolate, std::move(bytes_copy), length, context, std::move(resolver));
// Pass ownership to the unique_ptr in {jobs_}.

View File

@ -75,7 +75,7 @@ class V8_EXPORT_PRIVATE WasmEngine {
// The {is_shared} flag indicates if the bytes backing the module could
// be shared across threads, i.e. could be concurrently modified.
void AsyncCompile(Isolate* isolate,
std::shared_ptr<CompilationResultResolver> resolver,
std::unique_ptr<CompilationResultResolver> resolver,
const ModuleWireBytes& bytes, bool is_shared);
// Begin an asynchronous instantiation of the given WASM module.
@ -86,7 +86,7 @@ class V8_EXPORT_PRIVATE WasmEngine {
std::shared_ptr<StreamingDecoder> StartStreamingCompilation(
Isolate* isolate, Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver);
std::unique_ptr<CompilationResultResolver> resolver);
// Exports the sharable parts of the given module object so that they can be
// transferred to a different Context/Isolate using the same engine.
@ -142,7 +142,7 @@ class V8_EXPORT_PRIVATE WasmEngine {
AsyncCompileJob* CreateAsyncCompileJob(
Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, size_t length,
Handle<Context> context,
std::shared_ptr<CompilationResultResolver> resolver);
std::unique_ptr<CompilationResultResolver> resolver);
std::unique_ptr<WasmCodeManager> code_manager_;
WasmMemoryTracker memory_tracker_;

View File

@ -29,37 +29,11 @@ namespace v8 {
class WasmStreaming::WasmStreamingImpl {
public:
WasmStreamingImpl(
Isolate* isolate,
std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
: isolate_(isolate), resolver_(std::move(resolver)) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
i_isolate, handle(i_isolate->context(), i_isolate), resolver_);
}
void OnBytesReceived(const uint8_t* bytes, size_t size) {}
void OnBytesReceived(const uint8_t* bytes, size_t size) {
streaming_decoder_->OnBytesReceived(i::Vector<const uint8_t>(bytes, size));
}
void Finish() { streaming_decoder_->Finish(); }
void Finish() {}
void Abort(MaybeLocal<Value> exception) {
i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
streaming_decoder_->Abort();
// If no exception value is provided, we do not reject the promise. This can
// happen when streaming compilation gets aborted when no script execution
// is allowed anymore, e.g. when a browser tab gets refreshed.
if (exception.IsEmpty()) return;
resolver_->OnCompilationFailed(
Utils::OpenHandle(*exception.ToLocalChecked()));
}
private:
Isolate* isolate_ = nullptr;
std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
void Abort(MaybeLocal<Value> exception) {}
};
WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl)
@ -202,6 +176,30 @@ i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
}
void WebAssemblyCompileStreaming(
const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
// Manually create a promise and reject it.
Local<Context> context = isolate->GetCurrentContext();
ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(resolver->GetPromise());
ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compileStreaming()");
thrower.CompileError("Wasm code generation disallowed by embedder");
auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
CHECK_IMPLIES(!maybe.FromMaybe(false),
i_isolate->has_scheduled_exception());
return;
}
MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
DCHECK_NOT_NULL(i_isolate->wasm_compile_streaming_callback());
i_isolate->wasm_compile_streaming_callback()(args);
}
namespace {
// This class resolves the result of WebAssembly.compile. It just places the
// compilation result in the supplied {promise}.
@ -215,8 +213,6 @@ class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
}
void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
if (finished_) return;
finished_ = true;
i::MaybeHandle<i::Object> promise_result =
i::JSPromise::Resolve(promise_, result);
CHECK_EQ(promise_result.is_null(),
@ -224,8 +220,6 @@ class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
}
void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
if (finished_) return;
finished_ = true;
i::MaybeHandle<i::Object> promise_result =
i::JSPromise::Reject(promise_, error_reason);
CHECK_EQ(promise_result.is_null(),
@ -233,7 +227,6 @@ class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
}
private:
bool finished_ = false;
i::Handle<i::JSPromise> promise_;
};
@ -357,8 +350,6 @@ class AsyncInstantiateCompileResultResolver
}
void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
if (finished_) return;
finished_ = true;
isolate_->wasm_engine()->AsyncInstantiate(
isolate_,
base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
@ -367,15 +358,12 @@ class AsyncInstantiateCompileResultResolver
}
void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
if (finished_) return;
finished_ = true;
i::MaybeHandle<i::Object> promise_result =
i::JSPromise::Reject(promise_, error_reason);
CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
}
private:
bool finished_ = false;
i::Isolate* isolate_;
i::Handle<i::JSPromise> promise_;
i::MaybeHandle<i::JSReceiver> maybe_imports_;
@ -402,7 +390,7 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(promise);
std::shared_ptr<i::wasm::CompilationResultResolver> resolver(
std::unique_ptr<i::wasm::CompilationResultResolver> resolver(
new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
bool is_shared = false;
@ -416,61 +404,6 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
is_shared);
}
// WebAssembly.compileStreaming(Promise<Response>) -> Promise
void WebAssemblyCompileStreaming(
const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
HandleScope scope(isolate);
ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
Local<Context> context = isolate->GetCurrentContext();
// Create and assign the return value of this function.
ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
Local<Promise> promise = result_resolver->GetPromise();
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(promise);
// Prepare the CompilationResultResolver for the compilation.
auto resolver = std::make_shared<AsyncCompilationResolver>(
i_isolate, Utils::OpenHandle(*promise));
if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
thrower.CompileError("Wasm code generation disallowed by embedder");
resolver->OnCompilationFailed(thrower.Reify());
return;
}
// Allocate the streaming decoder in a Managed so we can pass it to the
// embedder.
i::Handle<i::Managed<WasmStreaming>> data =
i::Managed<WasmStreaming>::Allocate(
i_isolate, 0,
base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
resolver));
DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
ASSIGN(
v8::Function, compile_callback,
v8::Function::New(context, i_isolate->wasm_streaming_callback(),
Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
// The parameter may be of type {Response} or of type {Promise<Response>}.
// Treat either case of parameter as Promise.resolve(parameter)
// as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
// Ending with:
// return Promise.resolve(parameter).then(compile_callback);
ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
// We do not have any use of the result here. The {compile_callback} will
// start streaming compilation, which will eventually resolve the promise we
// set as result value.
USE(input_resolver->GetPromise()->Then(context, compile_callback));
}
// WebAssembly.validate(bytes) -> bool
void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
@ -630,6 +563,40 @@ MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
return Utils::ToLocal(instance_object.ToHandleChecked());
}
void WebAssemblyInstantiateCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) {
DCHECK_GE(args.Length(), 1);
Isolate* isolate = args.GetIsolate();
MicrotasksScope does_not_run_microtasks(isolate,
MicrotasksScope::kDoNotRunMicrotasks);
HandleScope scope(args.GetIsolate());
Local<Context> context = isolate->GetCurrentContext();
Local<Value> module = args[0];
const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
Local<Value> instance;
if (!WebAssemblyInstantiateImpl(isolate, module, args.Data())
.ToLocal(&instance)) {
return;
}
Local<Object> ret = Object::New(isolate);
Local<String> instance_name =
String::NewFromOneByte(isolate, instance_str,
NewStringType::kInternalized)
.ToLocalChecked();
Local<String> module_name =
String::NewFromOneByte(isolate, module_str, NewStringType::kInternalized)
.ToLocalChecked();
CHECK(ret->CreateDataProperty(context, instance_name, instance).IsJust());
CHECK(ret->CreateDataProperty(context, module_name, module).IsJust());
args.GetReturnValue().Set(ret);
}
// new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
@ -667,76 +634,27 @@ void WebAssemblyInstantiateStreaming(
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i_isolate->CountUsage(
v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
// we use i_isolate in DCHECKS in the ASSIGN statements.
USE(i_isolate);
MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
HandleScope scope(isolate);
Local<Context> context = isolate->GetCurrentContext();
ScheduledErrorThrower thrower(i_isolate,
"WebAssembly.instantiateStreaming()");
ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
Local<Value> first_arg_value = args[0];
// Create and assign the return value of this function.
ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
Local<Promise> promise = result_resolver->GetPromise();
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(promise);
ASSIGN(Function, compileStreaming,
Function::New(context, WebAssemblyCompileStreaming));
ASSIGN(Value, compile_retval,
compileStreaming->Call(context, args.Holder(), 1, &first_arg_value));
Local<Promise> module_promise = Local<Promise>::Cast(compile_retval);
// Create an InstantiateResultResolver in case there is an issue with the
// passed parameters.
std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
new InstantiateModuleResultResolver(i_isolate,
Utils::OpenHandle(*promise)));
if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
thrower.CompileError("Wasm code generation disallowed by embedder");
resolver->OnInstantiationFailed(thrower.Reify());
return;
}
// If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
Local<Value> ffi = args[1];
i::MaybeHandle<i::JSReceiver> maybe_imports =
GetValueAsImports(ffi, &thrower);
if (thrower.error()) {
resolver->OnInstantiationFailed(thrower.Reify());
return;
}
// We start compilation now, we have no use for the
// {InstantiationResultResolver}.
resolver.reset();
std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
new AsyncInstantiateCompileResultResolver(
i_isolate, Utils::OpenHandle(*promise), maybe_imports));
// Allocate the streaming decoder in a Managed so we can pass it to the
// embedder.
i::Handle<i::Managed<WasmStreaming>> data =
i::Managed<WasmStreaming>::Allocate(
i_isolate, 0,
base::make_unique<WasmStreaming::WasmStreamingImpl>(
isolate, compilation_resolver));
DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
ASSIGN(
v8::Function, compile_callback,
v8::Function::New(context, i_isolate->wasm_streaming_callback(),
Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
// The parameter may be of type {Response} or of type {Promise<Response>}.
// Treat either case of parameter as Promise.resolve(parameter)
// as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
// Ending with:
// return Promise.resolve(parameter).then(compile_callback);
ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
// We do not have any use of the result here. The {compile_callback} will
// start streaming compilation, which will eventually resolve the promise we
// set as result value.
USE(input_resolver->GetPromise()->Then(context, compile_callback));
DCHECK(!module_promise.IsEmpty());
Local<Value> data = args[1];
ASSIGN(Function, instantiate_impl,
Function::New(context, WebAssemblyInstantiateCallback, data));
ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
args.GetReturnValue().Set(result);
}
// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
@ -802,7 +720,7 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
// {InstantiationResultResolver}.
resolver.reset();
std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
std::unique_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
new AsyncInstantiateCompileResultResolver(
i_isolate, Utils::OpenHandle(*promise), maybe_imports));
@ -1470,7 +1388,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
if (isolate->wasm_streaming_callback() != nullptr) {
if (isolate->wasm_compile_streaming_callback() != nullptr) {
InstallFunc(isolate, webassembly, "compileStreaming",
WebAssemblyCompileStreaming, 1);
InstallFunc(isolate, webassembly, "instantiateStreaming",

View File

@ -59,7 +59,6 @@
#include "src/unicode-inl.h"
#include "src/utils.h"
#include "src/vm-state.h"
#include "src/wasm/wasm-js.h"
#include "test/cctest/heap/heap-tester.h"
#include "test/cctest/heap/heap-utils.h"
@ -28257,123 +28256,22 @@ TEST(PersistentValueMap) {
map.Set("key", value);
}
namespace {
bool wasm_streaming_callback_got_called = false;
bool wasm_streaming_data_got_collected = false;
void WasmStreamingTestFinalizer(const v8::WeakCallbackInfo<void>& data) {
CHECK(!wasm_streaming_data_got_collected);
wasm_streaming_data_got_collected = true;
i::JSObject** p = reinterpret_cast<i::JSObject**>(data.GetParameter());
i::GlobalHandles::Destroy(reinterpret_cast<i::Object**>(p));
}
void WasmStreamingCallbackTestCallbackIsCalled(
const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(!wasm_streaming_callback_got_called);
wasm_streaming_callback_got_called = true;
i::Handle<i::Object> global_handle =
reinterpret_cast<i::Isolate*>(args.GetIsolate())
->global_handles()
->Create(*v8::Utils::OpenHandle(*args.Data()));
i::GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
WasmStreamingTestFinalizer,
v8::WeakCallbackType::kParameter);
}
void WasmStreamingCallbackTestOnBytesReceived(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::shared_ptr<v8::WasmStreaming> streaming =
v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
// The first bytes of the WebAssembly magic word.
const uint8_t bytes[]{0x00, 0x61, 0x73};
streaming->OnBytesReceived(bytes, arraysize(bytes));
}
void WasmStreamingCallbackTestFinishWithSuccess(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::shared_ptr<v8::WasmStreaming> streaming =
v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
// The bytes of a minimal WebAssembly module.
const uint8_t bytes[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00};
streaming->OnBytesReceived(bytes, arraysize(bytes));
streaming->Finish();
}
void WasmStreamingCallbackTestFinishWithFailure(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::shared_ptr<v8::WasmStreaming> streaming =
v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
streaming->Finish();
}
void WasmStreamingCallbackTestAbortWithReject(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::shared_ptr<v8::WasmStreaming> streaming =
v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
streaming->Abort(v8::Object::New(args.GetIsolate()));
}
void WasmStreamingCallbackTestAbortNoReject(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::shared_ptr<v8::WasmStreaming> streaming =
v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
streaming->Abort({});
}
void TestWasmStreaming(v8::WasmStreamingCallback callback,
v8::Promise::PromiseState expected_state) {
CcTest::isolate()->SetWasmStreamingCallback(callback);
TEST(WasmStreamingAbort) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
// Call {WebAssembly.compileStreaming} with {null} as parameter. The parameter
// is only really processed by the embedder, so for this test the value is
// irrelevant.
v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(
CompileRun("WebAssembly.compileStreaming(null)"));
EmptyMessageQueues(isolate);
CHECK_EQ(expected_state, promise->State());
v8::WasmModuleObjectBuilderStreaming streaming(isolate);
streaming.Abort(v8::Object::New(isolate));
CHECK_EQ(streaming.GetPromise()->State(), v8::Promise::kRejected);
}
} // namespace
TEST(WasmStreamingCallback) {
TestWasmStreaming(WasmStreamingCallbackTestCallbackIsCalled,
v8::Promise::kPending);
CHECK(wasm_streaming_callback_got_called);
CcTest::CollectAllAvailableGarbage();
CHECK(wasm_streaming_data_got_collected);
}
TEST(WasmStreamingOnBytesReceived) {
TestWasmStreaming(WasmStreamingCallbackTestOnBytesReceived,
v8::Promise::kPending);
}
TEST(WasmStreamingFinishWithSuccess) {
TestWasmStreaming(WasmStreamingCallbackTestFinishWithSuccess,
v8::Promise::kFulfilled);
}
TEST(WasmStreamingFinishWithFailure) {
TestWasmStreaming(WasmStreamingCallbackTestFinishWithFailure,
v8::Promise::kRejected);
}
TEST(WasmStreamingAbortWithReject) {
TestWasmStreaming(WasmStreamingCallbackTestAbortWithReject,
v8::Promise::kRejected);
}
TEST(WasmStreamingAbortWithoutReject) {
TestWasmStreaming(WasmStreamingCallbackTestAbortNoReject,
v8::Promise::kPending);
TEST(WasmStreamingAbortNoReject) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
v8::WasmModuleObjectBuilderStreaming streaming(isolate);
streaming.Abort({});
CHECK_EQ(streaming.GetPromise()->State(), v8::Promise::kPending);
}
enum class AtomicsWaitCallbackAction {

View File

@ -114,7 +114,7 @@ class StreamTester {
stream_ = i_isolate->wasm_engine()->StartStreamingCompilation(
i_isolate, v8::Utils::OpenHandle(*context),
std::make_shared<TestResolver>(&state_));
base::make_unique<TestResolver>(&state_));
}
std::shared_ptr<StreamingDecoder> stream() { return stream_; }

View File

@ -69,7 +69,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
bool done = false;
i_isolate->wasm_engine()->AsyncCompile(
i_isolate, std::make_shared<AsyncFuzzerResolver>(i_isolate, &done),
i_isolate, base::make_unique<AsyncFuzzerResolver>(i_isolate, &done),
ModuleWireBytes(data, data + size), false);
// Wait for the promise to resolve.