V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-js.cc
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/wasm/wasm-js.h"
6 
7 #include "src/api-inl.h"
8 #include "src/api-natives.h"
9 #include "src/assert-scope.h"
10 #include "src/ast/ast.h"
11 #include "src/execution.h"
12 #include "src/handles.h"
13 #include "src/heap/factory.h"
14 #include "src/isolate.h"
15 #include "src/objects-inl.h"
16 #include "src/objects/js-promise-inl.h"
17 #include "src/objects/templates.h"
18 #include "src/parsing/parse-info.h"
19 #include "src/trap-handler/trap-handler.h"
20 #include "src/wasm/streaming-decoder.h"
21 #include "src/wasm/wasm-engine.h"
22 #include "src/wasm/wasm-limits.h"
23 #include "src/wasm/wasm-memory.h"
24 #include "src/wasm/wasm-objects-inl.h"
25 #include "src/wasm/wasm-serialization.h"
26 
28 
29 namespace v8 {
30 
32  public:
34  Isolate* isolate,
35  std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
36  : isolate_(isolate), resolver_(std::move(resolver)) {
37  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
38  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
39  streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
40  i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
41  resolver_);
42  }
43 
44  void OnBytesReceived(const uint8_t* bytes, size_t size) {
45  streaming_decoder_->OnBytesReceived(i::Vector<const uint8_t>(bytes, size));
46  }
47  void Finish() { streaming_decoder_->Finish(); }
48 
49  void Abort(MaybeLocal<Value> exception) {
50  i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
51  streaming_decoder_->Abort();
52 
53  // If no exception value is provided, we do not reject the promise. This can
54  // happen when streaming compilation gets aborted when no script execution
55  // is allowed anymore, e.g. when a browser tab gets refreshed.
56  if (exception.IsEmpty()) return;
57 
58  resolver_->OnCompilationFailed(
59  Utils::OpenHandle(*exception.ToLocalChecked()));
60  }
61 
62  void SetModuleCompiledCallback(ModuleCompiledCallback callback,
63  intptr_t data) {
64  // Wrap the embedder callback here so we can also wrap the result as a
65  // Local<WasmCompiledModule> here.
66  streaming_decoder_->SetModuleCompiledCallback(
67  [callback, data](i::Handle<i::WasmModuleObject> module_object) {
68  callback(data, Local<WasmCompiledModule>::Cast(Utils::ToLocal(
69  i::Handle<i::JSObject>::cast(module_object))));
70  });
71  }
72 
73  bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
74  if (!i::wasm::IsSupportedVersion(reinterpret_cast<i::Isolate*>(isolate_),
75  {bytes, size}))
76  return false;
77  return streaming_decoder_->SetCompiledModuleBytes({bytes, size});
78  }
79 
80  private:
81  Isolate* isolate_ = nullptr;
82  std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
83  std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
84 };
85 
86 WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl)
87  : impl_(std::move(impl)) {}
88 
89 // The destructor is defined here because we have a unique_ptr with forward
90 // declaration.
91 WasmStreaming::~WasmStreaming() = default;
92 
93 void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
94  impl_->OnBytesReceived(bytes, size);
95 }
96 
97 void WasmStreaming::Finish() { impl_->Finish(); }
98 
100  impl_->Abort(exception);
101 }
102 
104  intptr_t data) {
105  impl_->SetModuleCompiledCallback(callback, data);
106 }
107 
108 bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
109  return impl_->SetCompiledModuleBytes(bytes, size);
110 }
111 
112 // static
113 std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
114  Local<Value> value) {
115  i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate));
116  auto managed =
117  i::Handle<i::Managed<WasmStreaming>>::cast(Utils::OpenHandle(*value));
118  return managed->get();
119 }
120 
121 namespace {
122 
123 #define ASSIGN(type, var, expr) \
124  Local<type> var; \
125  do { \
126  if (!expr.ToLocal(&var)) { \
127  DCHECK(i_isolate->has_scheduled_exception()); \
128  return; \
129  } else { \
130  DCHECK(!i_isolate->has_scheduled_exception()); \
131  } \
132  } while (false)
133 
134 // Like an ErrorThrower, but turns all pending exceptions into scheduled
135 // exceptions when going out of scope. Use this in API methods.
136 // Note that pending exceptions are not necessarily created by the ErrorThrower,
137 // but e.g. by the wasm start function. There might also be a scheduled
138 // exception, created by another API call (e.g. v8::Object::Get). But there
139 // should never be both pending and scheduled exceptions.
140 class ScheduledErrorThrower : public ErrorThrower {
141  public:
142  ScheduledErrorThrower(i::Isolate* isolate, const char* context)
143  : ErrorThrower(isolate, context) {}
144 
145  ~ScheduledErrorThrower();
146 };
147 
148 ScheduledErrorThrower::~ScheduledErrorThrower() {
149  // There should never be both a pending and a scheduled exception.
150  DCHECK(!isolate()->has_scheduled_exception() ||
151  !isolate()->has_pending_exception());
152  // Don't throw another error if there is already a scheduled error.
153  if (isolate()->has_scheduled_exception()) {
154  Reset();
155  } else if (isolate()->has_pending_exception()) {
156  Reset();
157  isolate()->OptionalRescheduleException(false);
158  } else if (error()) {
159  isolate()->ScheduleThrow(*Reify());
160  }
161 }
162 
163 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
164  return isolate->factory()->NewStringFromAsciiChecked(str);
165 }
166 Local<String> v8_str(Isolate* isolate, const char* str) {
167  return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
168 }
169 
170 i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule(
171  const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
172  i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);
173  if (!arg0->IsWasmModuleObject()) {
174  thrower->TypeError("Argument 0 must be a WebAssembly.Module");
175  return {};
176  }
177 
178  Local<Object> module_obj = Local<Object>::Cast(args[0]);
180  v8::Utils::OpenHandle(*module_obj));
181 }
182 
183 i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
185  bool* is_shared) {
186  const uint8_t* start = nullptr;
187  size_t length = 0;
188  v8::Local<v8::Value> source = args[0];
189  if (source->IsArrayBuffer()) {
190  // A raw array buffer was passed.
191  Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
192  ArrayBuffer::Contents contents = buffer->GetContents();
193 
194  start = reinterpret_cast<const uint8_t*>(contents.Data());
195  length = contents.ByteLength();
196  *is_shared = buffer->IsSharedArrayBuffer();
197  } else if (source->IsTypedArray()) {
198  // A TypedArray was passed.
199  Local<TypedArray> array = Local<TypedArray>::Cast(source);
200  Local<ArrayBuffer> buffer = array->Buffer();
201 
202  ArrayBuffer::Contents contents = buffer->GetContents();
203 
204  start =
205  reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
206  length = array->ByteLength();
207  *is_shared = buffer->IsSharedArrayBuffer();
208  } else {
209  thrower->TypeError("Argument 0 must be a buffer source");
210  }
211  DCHECK_IMPLIES(length, start != nullptr);
212  if (length == 0) {
213  thrower->CompileError("BufferSource argument is empty");
214  }
215  if (length > i::wasm::kV8MaxWasmModuleSize) {
216  thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
217  i::wasm::kV8MaxWasmModuleSize, length);
218  }
219  if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
220  return i::wasm::ModuleWireBytes(start, start + length);
221 }
222 
223 i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
224  ErrorThrower* thrower) {
225  if (arg->IsUndefined()) return {};
226 
227  if (!arg->IsObject()) {
228  thrower->TypeError("Argument 1 must be an object");
229  return {};
230  }
231  Local<Object> obj = Local<Object>::Cast(arg);
232  return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
233 }
234 
235 namespace {
236 // This class resolves the result of WebAssembly.compile. It just places the
237 // compilation result in the supplied {promise}.
238 class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
239  public:
240  AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
241  : promise_(isolate->global_handles()->Create(*promise)) {}
242 
243  ~AsyncCompilationResolver() override {
244  i::GlobalHandles::Destroy(promise_.location());
245  }
246 
247  void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
248  if (finished_) return;
249  finished_ = true;
250  i::MaybeHandle<i::Object> promise_result =
251  i::JSPromise::Resolve(promise_, result);
252  CHECK_EQ(promise_result.is_null(),
253  promise_->GetIsolate()->has_pending_exception());
254  }
255 
256  void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
257  if (finished_) return;
258  finished_ = true;
259  i::MaybeHandle<i::Object> promise_result =
260  i::JSPromise::Reject(promise_, error_reason);
261  CHECK_EQ(promise_result.is_null(),
262  promise_->GetIsolate()->has_pending_exception());
263  }
264 
265  private:
266  bool finished_ = false;
267  i::Handle<i::JSPromise> promise_;
268 };
269 
270 // This class resolves the result of WebAssembly.instantiate(module, imports).
271 // It just places the instantiation result in the supplied {promise}.
272 class InstantiateModuleResultResolver
273  : public i::wasm::InstantiationResultResolver {
274  public:
275  InstantiateModuleResultResolver(i::Isolate* isolate,
276  i::Handle<i::JSPromise> promise)
277  : promise_(isolate->global_handles()->Create(*promise)) {}
278 
279  ~InstantiateModuleResultResolver() override {
280  i::GlobalHandles::Destroy(promise_.location());
281  }
282 
283  void OnInstantiationSucceeded(
284  i::Handle<i::WasmInstanceObject> instance) override {
285  i::MaybeHandle<i::Object> promise_result =
286  i::JSPromise::Resolve(promise_, instance);
287  CHECK_EQ(promise_result.is_null(),
288  promise_->GetIsolate()->has_pending_exception());
289  }
290 
291  void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
292  i::MaybeHandle<i::Object> promise_result =
293  i::JSPromise::Reject(promise_, error_reason);
294  CHECK_EQ(promise_result.is_null(),
295  promise_->GetIsolate()->has_pending_exception());
296  }
297 
298  private:
299  i::Handle<i::JSPromise> promise_;
300 };
301 
302 // This class resolves the result of WebAssembly.instantiate(bytes, imports).
303 // For that it creates a new {JSObject} which contains both the provided
304 // {WasmModuleObject} and the resulting {WebAssemblyInstanceObject} itself.
305 class InstantiateBytesResultResolver
306  : public i::wasm::InstantiationResultResolver {
307  public:
308  InstantiateBytesResultResolver(i::Isolate* isolate,
309  i::Handle<i::JSPromise> promise,
311  : isolate_(isolate),
312  promise_(isolate_->global_handles()->Create(*promise)),
313  module_(isolate_->global_handles()->Create(*module)) {}
314 
315  ~InstantiateBytesResultResolver() override {
316  i::GlobalHandles::Destroy(promise_.location());
317  i::GlobalHandles::Destroy(module_.location());
318  }
319 
320  void OnInstantiationSucceeded(
321  i::Handle<i::WasmInstanceObject> instance) override {
322  // The result is a JSObject with 2 fields which contain the
323  // WasmInstanceObject and the WasmModuleObject.
324  i::Handle<i::JSObject> result =
325  isolate_->factory()->NewJSObject(isolate_->object_function());
326 
327  const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
328  i::Handle<i::String> instance_name =
329  isolate_->factory()
330  ->NewStringFromOneByte(i::Vector<const uint8_t>(
331  instance_str,
332  i::StrLength(reinterpret_cast<const char*>(instance_str))))
333  .ToHandleChecked();
334 
335  const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
336  i::Handle<i::String> module_name =
337  isolate_->factory()
338  ->NewStringFromOneByte(i::Vector<const uint8_t>(
339  module_str,
340  i::StrLength(reinterpret_cast<const char*>(module_str))))
341  .ToHandleChecked();
342 
343  i::JSObject::AddProperty(isolate_, result, instance_name, instance,
344  i::NONE);
345  i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);
346 
347  i::MaybeHandle<i::Object> promise_result =
348  i::JSPromise::Resolve(promise_, result);
349  CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
350  }
351 
352  void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
353  i::MaybeHandle<i::Object> promise_result =
354  i::JSPromise::Reject(promise_, error_reason);
355  CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
356  }
357 
358  private:
359  i::Isolate* isolate_;
360  i::Handle<i::JSPromise> promise_;
362 };
363 
364 // This class is the {CompilationResultResolver} for
365 // WebAssembly.instantiate(bytes, imports). When compilation finishes,
366 // {AsyncInstantiate} is started on the compilation result.
367 class AsyncInstantiateCompileResultResolver
368  : public i::wasm::CompilationResultResolver {
369  public:
370  AsyncInstantiateCompileResultResolver(
371  i::Isolate* isolate, i::Handle<i::JSPromise> promise,
372  i::MaybeHandle<i::JSReceiver> maybe_imports)
373  : isolate_(isolate),
374  promise_(isolate_->global_handles()->Create(*promise)),
375  maybe_imports_(maybe_imports.is_null()
376  ? maybe_imports
377  : isolate_->global_handles()->Create(
378  *maybe_imports.ToHandleChecked())) {}
379 
380  ~AsyncInstantiateCompileResultResolver() override {
381  i::GlobalHandles::Destroy(promise_.location());
382  if (!maybe_imports_.is_null()) {
383  i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
384  }
385  }
386 
387  void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
388  if (finished_) return;
389  finished_ = true;
390  isolate_->wasm_engine()->AsyncInstantiate(
391  isolate_,
392  base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
393  result),
394  result, maybe_imports_);
395  }
396 
397  void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
398  if (finished_) return;
399  finished_ = true;
400  i::MaybeHandle<i::Object> promise_result =
401  i::JSPromise::Reject(promise_, error_reason);
402  CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
403  }
404 
405  private:
406  bool finished_ = false;
407  i::Isolate* isolate_;
408  i::Handle<i::JSPromise> promise_;
409  i::MaybeHandle<i::JSReceiver> maybe_imports_;
410 };
411 
412 } // namespace
413 
414 // WebAssembly.compile(bytes) -> Promise
415 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
416  v8::Isolate* isolate = args.GetIsolate();
417  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
418 
419  HandleScope scope(isolate);
420  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
421 
422  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
423  thrower.CompileError("Wasm code generation disallowed by embedder");
424  }
425 
426  Local<Context> context = isolate->GetCurrentContext();
427  ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
428  Local<Promise> promise = promise_resolver->GetPromise();
429  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
430  return_value.Set(promise);
431 
432  std::shared_ptr<i::wasm::CompilationResultResolver> resolver(
433  new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
434 
435  bool is_shared = false;
436  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
437  if (thrower.error()) {
438  resolver->OnCompilationFailed(thrower.Reify());
439  return;
440  }
441  // Asynchronous compilation handles copying wire bytes if necessary.
442  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
443  i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
444  std::move(resolver), bytes, is_shared);
445 }
446 
447 // WebAssembly.compileStreaming(Promise<Response>) -> Promise
448 void WebAssemblyCompileStreaming(
450  v8::Isolate* isolate = args.GetIsolate();
451  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
452  HandleScope scope(isolate);
453  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
454  Local<Context> context = isolate->GetCurrentContext();
455 
456  // Create and assign the return value of this function.
457  ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
458  Local<Promise> promise = result_resolver->GetPromise();
459  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
460  return_value.Set(promise);
461 
462  // Prepare the CompilationResultResolver for the compilation.
463  auto resolver = std::make_shared<AsyncCompilationResolver>(
464  i_isolate, Utils::OpenHandle(*promise));
465 
466  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
467  thrower.CompileError("Wasm code generation disallowed by embedder");
468  resolver->OnCompilationFailed(thrower.Reify());
469  return;
470  }
471 
472  // Allocate the streaming decoder in a Managed so we can pass it to the
473  // embedder.
476  i_isolate, 0,
477  base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
478  resolver));
479 
480  DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
481  ASSIGN(
482  v8::Function, compile_callback,
483  v8::Function::New(context, i_isolate->wasm_streaming_callback(),
484  Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
485 
486  // The parameter may be of type {Response} or of type {Promise<Response>}.
487  // Treat either case of parameter as Promise.resolve(parameter)
488  // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
489 
490  // Ending with:
491  // return Promise.resolve(parameter).then(compile_callback);
492  ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
493  if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
494 
495  // We do not have any use of the result here. The {compile_callback} will
496  // start streaming compilation, which will eventually resolve the promise we
497  // set as result value.
498  USE(input_resolver->GetPromise()->Then(context, compile_callback));
499 }
500 
501 // WebAssembly.validate(bytes) -> bool
502 void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
503  v8::Isolate* isolate = args.GetIsolate();
504  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
505  HandleScope scope(isolate);
506  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
507 
508  bool is_shared = false;
509  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
510 
511  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
512 
513  if (thrower.error()) {
514  if (thrower.wasm_error()) thrower.Reset(); // Clear error.
515  return_value.Set(v8::False(isolate));
516  return;
517  }
518 
519  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
520  bool validated = false;
521  if (is_shared) {
522  // Make a copy of the wire bytes to avoid concurrent modification.
523  std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
524  memcpy(copy.get(), bytes.start(), bytes.length());
525  i::wasm::ModuleWireBytes bytes_copy(copy.get(),
526  copy.get() + bytes.length());
527  validated = i_isolate->wasm_engine()->SyncValidate(
528  i_isolate, enabled_features, bytes_copy);
529  } else {
530  // The wire bytes are not shared, OK to use them directly.
531  validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
532  enabled_features, bytes);
533  }
534 
535  return_value.Set(Boolean::New(isolate, validated));
536 }
537 
538 // new WebAssembly.Module(bytes) -> WebAssembly.Module
539 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
540  v8::Isolate* isolate = args.GetIsolate();
541  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
542  if (i_isolate->wasm_module_callback()(args)) return;
543 
544  HandleScope scope(isolate);
545  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
546 
547  if (!args.IsConstructCall()) {
548  thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
549  return;
550  }
551  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
552  thrower.CompileError("Wasm code generation disallowed by embedder");
553  return;
554  }
555 
556  bool is_shared = false;
557  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
558 
559  if (thrower.error()) {
560  return;
561  }
562  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
563  i::MaybeHandle<i::Object> module_obj;
564  if (is_shared) {
565  // Make a copy of the wire bytes to avoid concurrent modification.
566  std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
567  memcpy(copy.get(), bytes.start(), bytes.length());
568  i::wasm::ModuleWireBytes bytes_copy(copy.get(),
569  copy.get() + bytes.length());
570  module_obj = i_isolate->wasm_engine()->SyncCompile(
571  i_isolate, enabled_features, &thrower, bytes_copy);
572  } else {
573  // The wire bytes are not shared, OK to use them directly.
574  module_obj = i_isolate->wasm_engine()->SyncCompile(
575  i_isolate, enabled_features, &thrower, bytes);
576  }
577 
578  if (module_obj.is_null()) return;
579 
580  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
581  return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
582 }
583 
584 // WebAssembly.Module.imports(module) -> Array<Import>
585 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
586  HandleScope scope(args.GetIsolate());
587  v8::Isolate* isolate = args.GetIsolate();
588  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
589  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
590 
591  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
592  if (thrower.error()) return;
593  auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
594  args.GetReturnValue().Set(Utils::ToLocal(imports));
595 }
596 
597 // WebAssembly.Module.exports(module) -> Array<Export>
598 void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
599  HandleScope scope(args.GetIsolate());
600  v8::Isolate* isolate = args.GetIsolate();
601  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
602  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
603 
604  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
605  if (thrower.error()) return;
606  auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
607  args.GetReturnValue().Set(Utils::ToLocal(exports));
608 }
609 
610 // WebAssembly.Module.customSections(module, name) -> Array<Section>
611 void WebAssemblyModuleCustomSections(
613  HandleScope scope(args.GetIsolate());
614  v8::Isolate* isolate = args.GetIsolate();
615  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
616  ScheduledErrorThrower thrower(i_isolate,
617  "WebAssembly.Module.customSections()");
618 
619  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
620  if (thrower.error()) return;
621 
622  i::MaybeHandle<i::Object> maybe_name =
623  i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
625  if (!maybe_name.ToHandle(&name)) return;
626  auto custom_sections =
627  i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
628  i::Handle<i::String>::cast(name), &thrower);
629  if (thrower.error()) return;
630  args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
631 }
632 
633 MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
634  Local<Value> module,
635  Local<Value> ffi) {
636  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
637 
638  i::MaybeHandle<i::Object> instance_object;
639  {
640  ScheduledErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
641 
642  // TODO(ahaas): These checks on the module should not be necessary here They
643  // are just a workaround for https://crbug.com/837417.
644  i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
645  if (!module_obj->IsWasmModuleObject()) {
646  thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
647  return {};
648  }
649 
650  i::MaybeHandle<i::JSReceiver> maybe_imports =
651  GetValueAsImports(ffi, &thrower);
652  if (thrower.error()) return {};
653 
654  instance_object = i_isolate->wasm_engine()->SyncInstantiate(
655  i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
656  maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
657  }
658 
659  DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
660  if (instance_object.is_null()) return {};
661  return Utils::ToLocal(instance_object.ToHandleChecked());
662 }
663 
664 // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
665 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
666  Isolate* isolate = args.GetIsolate();
667  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
668  i_isolate->CountUsage(
669  v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
670 
671  HandleScope scope(args.GetIsolate());
672  if (i_isolate->wasm_instance_callback()(args)) return;
673 
674  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
675  if (!args.IsConstructCall()) {
676  thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
677  return;
678  }
679 
680  GetFirstArgumentAsModule(args, &thrower);
681  if (thrower.error()) return;
682 
683  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
684  // We'll check for that in WebAssemblyInstantiateImpl.
685  Local<Value> data = args[1];
686 
687  Local<Value> instance;
688  if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
689  args.GetReturnValue().Set(instance);
690  }
691 }
692 
693 void WebAssemblyInstantiateStreaming(
695  v8::Isolate* isolate = args.GetIsolate();
696  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
697  i_isolate->CountUsage(
698  v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
699 
700  HandleScope scope(isolate);
701  Local<Context> context = isolate->GetCurrentContext();
702  ScheduledErrorThrower thrower(i_isolate,
703  "WebAssembly.instantiateStreaming()");
704 
705  // Create and assign the return value of this function.
706  ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
707  Local<Promise> promise = result_resolver->GetPromise();
708  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
709  return_value.Set(promise);
710 
711  // Create an InstantiateResultResolver in case there is an issue with the
712  // passed parameters.
713  std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
714  new InstantiateModuleResultResolver(i_isolate,
715  Utils::OpenHandle(*promise)));
716 
717  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
718  thrower.CompileError("Wasm code generation disallowed by embedder");
719  resolver->OnInstantiationFailed(thrower.Reify());
720  return;
721  }
722 
723  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
724  Local<Value> ffi = args[1];
725  i::MaybeHandle<i::JSReceiver> maybe_imports =
726  GetValueAsImports(ffi, &thrower);
727 
728  if (thrower.error()) {
729  resolver->OnInstantiationFailed(thrower.Reify());
730  return;
731  }
732 
733  // We start compilation now, we have no use for the
734  // {InstantiationResultResolver}.
735  resolver.reset();
736 
737  std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
738  new AsyncInstantiateCompileResultResolver(
739  i_isolate, Utils::OpenHandle(*promise), maybe_imports));
740 
741  // Allocate the streaming decoder in a Managed so we can pass it to the
742  // embedder.
745  i_isolate, 0,
746  base::make_unique<WasmStreaming::WasmStreamingImpl>(
747  isolate, compilation_resolver));
748 
749  DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
750  ASSIGN(
751  v8::Function, compile_callback,
752  v8::Function::New(context, i_isolate->wasm_streaming_callback(),
753  Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
754 
755  // The parameter may be of type {Response} or of type {Promise<Response>}.
756  // Treat either case of parameter as Promise.resolve(parameter)
757  // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
758 
759  // Ending with:
760  // return Promise.resolve(parameter).then(compile_callback);
761  ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
762  if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
763 
764  // We do not have any use of the result here. The {compile_callback} will
765  // start streaming compilation, which will eventually resolve the promise we
766  // set as result value.
767  USE(input_resolver->GetPromise()->Then(context, compile_callback));
768 }
769 
770 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
771 // WebAssembly.instantiate(bytes, imports) ->
772 // {module: WebAssembly.Module, instance: WebAssembly.Instance}
773 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
774  v8::Isolate* isolate = args.GetIsolate();
775  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
776  i_isolate->CountUsage(
777  v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
778 
779  ScheduledErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
780 
781  HandleScope scope(isolate);
782 
783  Local<Context> context = isolate->GetCurrentContext();
784 
785  ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
786  Local<Promise> promise = promise_resolver->GetPromise();
787  args.GetReturnValue().Set(promise);
788 
789  std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
790  new InstantiateModuleResultResolver(i_isolate,
791  Utils::OpenHandle(*promise)));
792 
793  Local<Value> first_arg_value = args[0];
794  i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
795  if (!first_arg->IsJSObject()) {
796  thrower.TypeError(
797  "Argument 0 must be a buffer source or a WebAssembly.Module object");
798  resolver->OnInstantiationFailed(thrower.Reify());
799  return;
800  }
801 
802  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
803  Local<Value> ffi = args[1];
804  i::MaybeHandle<i::JSReceiver> maybe_imports =
805  GetValueAsImports(ffi, &thrower);
806 
807  if (thrower.error()) {
808  resolver->OnInstantiationFailed(thrower.Reify());
809  return;
810  }
811 
812  if (first_arg->IsWasmModuleObject()) {
813  i::Handle<i::WasmModuleObject> module_obj =
815 
816  i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
817  module_obj, maybe_imports);
818  return;
819  }
820 
821  bool is_shared = false;
822  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
823  if (thrower.error()) {
824  resolver->OnInstantiationFailed(thrower.Reify());
825  return;
826  }
827 
828  // We start compilation now, we have no use for the
829  // {InstantiationResultResolver}.
830  resolver.reset();
831 
832  std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
833  new AsyncInstantiateCompileResultResolver(
834  i_isolate, Utils::OpenHandle(*promise), maybe_imports));
835 
836  // The first parameter is a buffer source, we have to check if we are allowed
837  // to compile it.
838  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
839  thrower.CompileError("Wasm code generation disallowed by embedder");
840  compilation_resolver->OnCompilationFailed(thrower.Reify());
841  return;
842  }
843 
844  // Asynchronous compilation handles copying wire bytes if necessary.
845  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
846  i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
847  std::move(compilation_resolver), bytes,
848  is_shared);
849 }
850 
851 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
852  Local<Context> context, Local<v8::Object> object,
853  Local<String> property, int64_t* result,
854  int64_t lower_bound, uint64_t upper_bound) {
855  v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
856  v8::Local<v8::Value> value;
857  if (maybe.ToLocal(&value)) {
858  int64_t number;
859  if (!value->IntegerValue(context).To(&number)) return false;
860  if (number < lower_bound) {
861  thrower->RangeError("Property value %" PRId64
862  " is below the lower bound %" PRIx64,
863  number, lower_bound);
864  return false;
865  }
866  if (number > static_cast<int64_t>(upper_bound)) {
867  thrower->RangeError("Property value %" PRId64
868  " is above the upper bound %" PRIu64,
869  number, upper_bound);
870  return false;
871  }
872  *result = static_cast<int>(number);
873  return true;
874  }
875  return false;
876 }
877 
878 // new WebAssembly.Table(args) -> WebAssembly.Table
879 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
880  v8::Isolate* isolate = args.GetIsolate();
881  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
882  HandleScope scope(isolate);
883  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
884  if (!args.IsConstructCall()) {
885  thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
886  return;
887  }
888  if (!args[0]->IsObject()) {
889  thrower.TypeError("Argument 0 must be a table descriptor");
890  return;
891  }
892  Local<Context> context = isolate->GetCurrentContext();
893  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
894  // The descriptor's 'element'.
895  {
897  descriptor->Get(context, v8_str(isolate, "element"));
898  v8::Local<v8::Value> value;
899  if (!maybe.ToLocal(&value)) return;
900  v8::Local<v8::String> string;
901  if (!value->ToString(context).ToLocal(&string)) return;
902  if (!string->StringEquals(v8_str(isolate, "anyfunc"))) {
903  thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
904  return;
905  }
906  }
907  // The descriptor's 'initial'.
908  int64_t initial = 0;
909  if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
910  v8_str(isolate, "initial"), &initial, 0,
911  i::FLAG_wasm_max_table_size)) {
912  return;
913  }
914  // The descriptor's 'maximum'.
915  int64_t maximum = -1;
916  Local<String> maximum_key = v8_str(isolate, "maximum");
917  Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
918 
919  if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
920  if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
921  &maximum, initial,
922  i::wasm::kSpecMaxWasmTableSize)) {
923  return;
924  }
925  }
926 
927  i::Handle<i::FixedArray> fixed_array;
928  i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
929  i_isolate, static_cast<uint32_t>(initial), maximum, &fixed_array);
930  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
931  return_value.Set(Utils::ToLocal(table_obj));
932 }
933 
934 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
935  v8::Isolate* isolate = args.GetIsolate();
936  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
937  HandleScope scope(isolate);
938  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
939  if (!args.IsConstructCall()) {
940  thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
941  return;
942  }
943  if (!args[0]->IsObject()) {
944  thrower.TypeError("Argument 0 must be a memory descriptor");
945  return;
946  }
947  Local<Context> context = isolate->GetCurrentContext();
948  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
949  // The descriptor's 'initial'.
950  int64_t initial = 0;
951  if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
952  v8_str(isolate, "initial"), &initial, 0,
953  i::wasm::max_mem_pages())) {
954  return;
955  }
956  // The descriptor's 'maximum'.
957  int64_t maximum = -1;
958  Local<String> maximum_key = v8_str(isolate, "maximum");
959  Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
960 
961  if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
962  if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
963  &maximum, initial,
964  i::wasm::kSpecMaxWasmMemoryPages)) {
965  return;
966  }
967  }
968 
969  bool is_shared_memory = false;
970  auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
971  if (enabled_features.threads) {
972  // Shared property of descriptor
973  Local<String> shared_key = v8_str(isolate, "shared");
974  Maybe<bool> has_shared = descriptor->Has(context, shared_key);
975  if (!has_shared.IsNothing() && has_shared.FromJust()) {
976  v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, shared_key);
977  v8::Local<v8::Value> value;
978  if (maybe.ToLocal(&value)) {
979  is_shared_memory = value->BooleanValue(isolate);
980  }
981  }
982  // Throw TypeError if shared is true, and the descriptor has no "maximum"
983  if (is_shared_memory && maximum == -1) {
984  thrower.TypeError(
985  "If shared is true, maximum property should be defined.");
986  }
987  }
988 
989  i::SharedFlag shared_flag =
990  is_shared_memory ? i::SharedFlag::kShared : i::SharedFlag::kNotShared;
992  size_t size = static_cast<size_t>(i::wasm::kWasmPageSize) *
993  static_cast<size_t>(initial);
994  if (!i::wasm::NewArrayBuffer(i_isolate, size, shared_flag)
995  .ToHandle(&buffer)) {
996  thrower.RangeError("could not allocate memory");
997  return;
998  }
999  if (buffer->is_shared()) {
1000  Maybe<bool> result =
1001  buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1002  if (!result.FromJust()) {
1003  thrower.TypeError(
1004  "Status of setting SetIntegrityLevel of buffer is false.");
1005  }
1006  }
1007  i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New(
1008  i_isolate, buffer, static_cast<int32_t>(maximum));
1009  args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
1010 }
1011 
1012 void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
1013  v8::Isolate* isolate = args.GetIsolate();
1014  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1015  HandleScope scope(isolate);
1016  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
1017  if (!args.IsConstructCall()) {
1018  thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
1019  return;
1020  }
1021  if (!args[0]->IsObject()) {
1022  thrower.TypeError("Argument 0 must be a global descriptor");
1023  return;
1024  }
1025  Local<Context> context = isolate->GetCurrentContext();
1026  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1027 
1028  // The descriptor's 'mutable'.
1029  bool is_mutable = false;
1030  {
1031  Local<String> mutable_key = v8_str(isolate, "mutable");
1032  v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
1033  v8::Local<v8::Value> value;
1034  if (maybe.ToLocal(&value)) {
1035  is_mutable = value->BooleanValue(isolate);
1036  }
1037  }
1038 
1039  // The descriptor's type, called 'value'. It is called 'value' because this
1040  // descriptor is planned to be re-used as the global's type for reflection,
1041  // so calling it 'type' is redundant.
1042  i::wasm::ValueType type;
1043  {
1045  descriptor->Get(context, v8_str(isolate, "value"));
1046  v8::Local<v8::Value> value;
1047  if (!maybe.ToLocal(&value)) return;
1048  v8::Local<v8::String> string;
1049  if (!value->ToString(context).ToLocal(&string)) return;
1050 
1051  if (string->StringEquals(v8_str(isolate, "i32"))) {
1052  type = i::wasm::kWasmI32;
1053  } else if (string->StringEquals(v8_str(isolate, "f32"))) {
1054  type = i::wasm::kWasmF32;
1055  } else if (string->StringEquals(v8_str(isolate, "f64"))) {
1056  type = i::wasm::kWasmF64;
1057  } else {
1058  thrower.TypeError(
1059  "Descriptor property 'value' must be 'i32', 'f32', or 'f64'");
1060  return;
1061  }
1062  }
1063 
1064  const uint32_t offset = 0;
1065  i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
1066  i::WasmGlobalObject::New(i_isolate, i::MaybeHandle<i::JSArrayBuffer>(),
1067  type, offset, is_mutable);
1068 
1069  i::Handle<i::WasmGlobalObject> global_obj;
1070  if (!maybe_global_obj.ToHandle(&global_obj)) {
1071  thrower.RangeError("could not allocate memory");
1072  return;
1073  }
1074 
1075  // Convert value to a WebAssembly value, the default value is 0.
1076  Local<v8::Value> value = Local<Value>::Cast(args[1]);
1077  switch (type) {
1078  case i::wasm::kWasmI32: {
1079  int32_t i32_value = 0;
1080  if (!value->IsUndefined()) {
1081  v8::Local<v8::Int32> int32_value;
1082  if (!value->ToInt32(context).ToLocal(&int32_value)) return;
1083  if (!int32_value->Int32Value(context).To(&i32_value)) return;
1084  }
1085  global_obj->SetI32(i32_value);
1086  break;
1087  }
1088  case i::wasm::kWasmF32: {
1089  float f32_value = 0;
1090  if (!value->IsUndefined()) {
1091  double f64_value = 0;
1092  v8::Local<v8::Number> number_value;
1093  if (!value->ToNumber(context).ToLocal(&number_value)) return;
1094  if (!number_value->NumberValue(context).To(&f64_value)) return;
1095  f32_value = static_cast<float>(f64_value);
1096  }
1097  global_obj->SetF32(f32_value);
1098  break;
1099  }
1100  case i::wasm::kWasmF64: {
1101  double f64_value = 0;
1102  if (!value->IsUndefined()) {
1103  v8::Local<v8::Number> number_value;
1104  if (!value->ToNumber(context).ToLocal(&number_value)) return;
1105  if (!number_value->NumberValue(context).To(&f64_value)) return;
1106  }
1107  global_obj->SetF64(f64_value);
1108  break;
1109  }
1110  default:
1111  UNREACHABLE();
1112  }
1113 
1114  i::Handle<i::JSObject> global_js_object(global_obj);
1115  args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
1116 }
1117 
1118 // WebAssembly.Exception
1119 void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
1120  v8::Isolate* isolate = args.GetIsolate();
1121  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1122  HandleScope scope(isolate);
1123  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Excepion()");
1124  thrower.TypeError("WebAssembly.Exception cannot be called");
1125 }
1126 
1127 constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
1128 constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
1129 constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
1130 constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
1131 
1132 #define EXTRACT_THIS(var, WasmType) \
1133  i::Handle<i::WasmType> var; \
1134  { \
1135  i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
1136  if (!this_arg->Is##WasmType()) { \
1137  thrower.TypeError("Receiver is not a %s", kName_##WasmType); \
1138  return; \
1139  } \
1140  var = i::Handle<i::WasmType>::cast(this_arg); \
1141  }
1142 
1143 void WebAssemblyInstanceGetExports(
1145  v8::Isolate* isolate = args.GetIsolate();
1146  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1147  HandleScope scope(isolate);
1148  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
1149  EXTRACT_THIS(receiver, WasmInstanceObject);
1150  i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
1151  args.GetReturnValue().Set(Utils::ToLocal(exports_object));
1152 }
1153 
1154 void WebAssemblyTableGetLength(
1156  v8::Isolate* isolate = args.GetIsolate();
1157  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1158  HandleScope scope(isolate);
1159  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
1160  EXTRACT_THIS(receiver, WasmTableObject);
1161  args.GetReturnValue().Set(
1162  v8::Number::New(isolate, receiver->current_length()));
1163 }
1164 
1165 // WebAssembly.Table.grow(num) -> num
1166 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1167  v8::Isolate* isolate = args.GetIsolate();
1168  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1169  HandleScope scope(isolate);
1170  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
1171  Local<Context> context = isolate->GetCurrentContext();
1172  EXTRACT_THIS(receiver, WasmTableObject);
1173 
1174  int64_t grow_by = 0;
1175  if (!args[0]->IntegerValue(context).To(&grow_by)) return;
1176  i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate);
1177  int old_size = old_array->length();
1178 
1179  int64_t max_size64 = receiver->maximum_length()->Number();
1180  if (max_size64 < 0 || max_size64 > i::FLAG_wasm_max_table_size) {
1181  max_size64 = i::FLAG_wasm_max_table_size;
1182  }
1183 
1184  if (grow_by < 0 || grow_by > max_size64 - old_size) {
1185  thrower.RangeError(grow_by < 0 ? "trying to shrink table"
1186  : "maximum table size exceeded");
1187  return;
1188  }
1189 
1190  int new_size = static_cast<int>(old_size + grow_by);
1191  receiver->Grow(i_isolate, static_cast<uint32_t>(new_size - old_size));
1192 
1193  if (new_size != old_size) {
1194  i::Handle<i::FixedArray> new_array =
1195  i_isolate->factory()->NewFixedArray(new_size);
1196  for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i));
1197  i::Object* null = i::ReadOnlyRoots(i_isolate).null_value();
1198  for (int i = old_size; i < new_size; ++i) new_array->set(i, null);
1199  receiver->set_functions(*new_array);
1200  }
1201 
1202  // TODO(gdeepti): use weak links for instances
1203  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1204  return_value.Set(old_size);
1205 }
1206 
1207 // WebAssembly.Table.get(num) -> JSFunction
1208 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1209  v8::Isolate* isolate = args.GetIsolate();
1210  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1211  HandleScope scope(isolate);
1212  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
1213  Local<Context> context = isolate->GetCurrentContext();
1214  EXTRACT_THIS(receiver, WasmTableObject);
1215  i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
1216  int64_t i = 0;
1217  if (!args[0]->IntegerValue(context).To(&i)) return;
1218  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1219  if (i < 0 || i >= array->length()) {
1220  thrower.RangeError("index out of bounds");
1221  return;
1222  }
1223 
1224  i::Handle<i::Object> value(array->get(static_cast<int>(i)), i_isolate);
1225  return_value.Set(Utils::ToLocal(value));
1226 }
1227 
1228 // WebAssembly.Table.set(num, JSFunction)
1229 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1230  v8::Isolate* isolate = args.GetIsolate();
1231  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1232  HandleScope scope(isolate);
1233  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
1234  Local<Context> context = isolate->GetCurrentContext();
1235  EXTRACT_THIS(receiver, WasmTableObject);
1236 
1237  // Parameter 0.
1238  int64_t index;
1239  if (!args[0]->IntegerValue(context).To(&index)) return;
1240 
1241  // Parameter 1.
1242  i::Handle<i::Object> value = Utils::OpenHandle(*args[1]);
1243  if (!value->IsNull(i_isolate) &&
1244  !i::WasmExportedFunction::IsWasmExportedFunction(*value)) {
1245  thrower.TypeError("Argument 1 must be null or a WebAssembly function");
1246  return;
1247  }
1248 
1249  if (index < 0 || index >= receiver->functions()->length()) {
1250  thrower.RangeError("index out of bounds");
1251  return;
1252  }
1253 
1254  i::WasmTableObject::Set(i_isolate, receiver, static_cast<int32_t>(index),
1255  value->IsNull(i_isolate)
1257  : i::Handle<i::JSFunction>::cast(value));
1258 }
1259 
1260 // WebAssembly.Memory.grow(num) -> num
1261 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1262  v8::Isolate* isolate = args.GetIsolate();
1263  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1264  HandleScope scope(isolate);
1265  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
1266  Local<Context> context = isolate->GetCurrentContext();
1267  EXTRACT_THIS(receiver, WasmMemoryObject);
1268 
1269  int64_t delta_size = 0;
1270  if (!args[0]->IntegerValue(context).To(&delta_size)) return;
1271 
1272  int64_t max_size64 = receiver->maximum_pages();
1273  if (max_size64 < 0 || max_size64 > int64_t{i::wasm::max_mem_pages()}) {
1274  max_size64 = i::wasm::max_mem_pages();
1275  }
1276  i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);
1277  if (!old_buffer->is_growable()) {
1278  thrower.RangeError("This memory cannot be grown");
1279  return;
1280  }
1281  int64_t old_size = old_buffer->byte_length() / i::wasm::kWasmPageSize;
1282  int64_t new_size64 = old_size + delta_size;
1283  if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) {
1284  thrower.RangeError(new_size64 < old_size ? "trying to shrink memory"
1285  : "maximum memory size exceeded");
1286  return;
1287  }
1288  int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver,
1289  static_cast<uint32_t>(delta_size));
1290  if (ret == -1) {
1291  thrower.RangeError("Unable to grow instance memory.");
1292  return;
1293  }
1294  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1295  return_value.Set(ret);
1296 }
1297 
1298 // WebAssembly.Memory.buffer -> ArrayBuffer
1299 void WebAssemblyMemoryGetBuffer(
1301  v8::Isolate* isolate = args.GetIsolate();
1302  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1303  HandleScope scope(isolate);
1304  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
1305  EXTRACT_THIS(receiver, WasmMemoryObject);
1306 
1307  i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
1308  DCHECK(buffer_obj->IsJSArrayBuffer());
1309  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
1310  i_isolate);
1311  if (buffer->is_shared()) {
1312  // TODO(gdeepti): More needed here for when cached buffer, and current
1313  // buffer are out of sync, handle that here when bounds checks, and Grow
1314  // are handled correctly.
1315  Maybe<bool> result =
1316  buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1317  if (!result.FromJust()) {
1318  thrower.TypeError(
1319  "Status of setting SetIntegrityLevel of buffer is false.");
1320  }
1321  }
1322  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1323  return_value.Set(Utils::ToLocal(buffer));
1324 }
1325 
1326 void WebAssemblyGlobalGetValueCommon(
1327  const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
1328  v8::Isolate* isolate = args.GetIsolate();
1329  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1330  HandleScope scope(isolate);
1331  ScheduledErrorThrower thrower(i_isolate, name);
1332  EXTRACT_THIS(receiver, WasmGlobalObject);
1333 
1334  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1335 
1336  switch (receiver->type()) {
1337  case i::wasm::kWasmI32:
1338  return_value.Set(receiver->GetI32());
1339  break;
1340  case i::wasm::kWasmI64:
1341  thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
1342  break;
1343  case i::wasm::kWasmF32:
1344  return_value.Set(receiver->GetF32());
1345  break;
1346  case i::wasm::kWasmF64:
1347  return_value.Set(receiver->GetF64());
1348  break;
1349  default:
1350  UNREACHABLE();
1351  }
1352 }
1353 
1354 // WebAssembly.Global.valueOf() -> num
1355 void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
1356  return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
1357 }
1358 
1359 // get WebAssembly.Global.value -> num
1360 void WebAssemblyGlobalGetValue(
1362  return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
1363 }
1364 
1365 // set WebAssembly.Global.value(num)
1366 void WebAssemblyGlobalSetValue(
1368  v8::Isolate* isolate = args.GetIsolate();
1369  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1370  HandleScope scope(isolate);
1371  Local<Context> context = isolate->GetCurrentContext();
1372  ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
1373  EXTRACT_THIS(receiver, WasmGlobalObject);
1374 
1375  if (!receiver->is_mutable()) {
1376  thrower.TypeError("Can't set the value of an immutable global.");
1377  return;
1378  }
1379 
1380  switch (receiver->type()) {
1381  case i::wasm::kWasmI32: {
1382  int32_t i32_value = 0;
1383  if (!args[0]->Int32Value(context).To(&i32_value)) return;
1384  receiver->SetI32(i32_value);
1385  break;
1386  }
1387  case i::wasm::kWasmI64:
1388  thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
1389  break;
1390  case i::wasm::kWasmF32: {
1391  double f64_value = 0;
1392  if (!args[0]->NumberValue(context).To(&f64_value)) return;
1393  receiver->SetF32(static_cast<float>(f64_value));
1394  break;
1395  }
1396  case i::wasm::kWasmF64: {
1397  double f64_value = 0;
1398  if (!args[0]->NumberValue(context).To(&f64_value)) return;
1399  receiver->SetF64(f64_value);
1400  break;
1401  }
1402  default:
1403  UNREACHABLE();
1404  }
1405 }
1406 
1407 } // namespace
1408 
1409 // TODO(titzer): we use the API to create the function template because the
1410 // internal guts are too ugly to replicate here.
1411 static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
1412  i::Isolate* i_isolate, FunctionCallback func) {
1413  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1414  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
1415  templ->ReadOnlyPrototype();
1416  return v8::Utils::OpenHandle(*templ);
1417 }
1418 
1419 static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
1420  i::Isolate* i_isolate) {
1421  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1422  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
1423  return v8::Utils::OpenHandle(*templ);
1424 }
1425 
1426 namespace internal {
1427 
1428 Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
1429  FunctionCallback func) {
1430  Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
1431  Handle<JSFunction> function =
1432  ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
1433  DCHECK(function->shared()->HasSharedName());
1434  return function;
1435 }
1436 
1437 Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
1438  const char* str, FunctionCallback func,
1439  int length = 0) {
1440  Handle<String> name = v8_str(isolate, str);
1441  Handle<JSFunction> function = CreateFunc(isolate, name, func);
1442  function->shared()->set_length(length);
1443  PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
1444  JSObject::AddProperty(isolate, object, name, function, attributes);
1445  return function;
1446 }
1447 
1448 Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
1449  return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
1450  .ToHandleChecked();
1451 }
1452 
1453 void InstallGetter(Isolate* isolate, Handle<JSObject> object,
1454  const char* str, FunctionCallback func) {
1455  Handle<String> name = v8_str(isolate, str);
1456  Handle<JSFunction> function =
1457  CreateFunc(isolate, GetterName(isolate, name), func);
1458 
1459  v8::PropertyAttribute attributes =
1460  static_cast<v8::PropertyAttribute>(v8::DontEnum);
1461  Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
1462  Utils::ToLocal(function),
1463  Local<Function>(), attributes);
1464 }
1465 
1466 Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
1467  return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
1468  .ToHandleChecked();
1469 }
1470 
1471 void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
1472  const char* str, FunctionCallback getter,
1473  FunctionCallback setter) {
1474  Handle<String> name = v8_str(isolate, str);
1475  Handle<JSFunction> getter_func =
1476  CreateFunc(isolate, GetterName(isolate, name), getter);
1477  Handle<JSFunction> setter_func =
1478  CreateFunc(isolate, SetterName(isolate, name), setter);
1479  setter_func->shared()->set_length(1);
1480 
1481  v8::PropertyAttribute attributes =
1482  static_cast<v8::PropertyAttribute>(v8::DontEnum);
1483 
1484  Utils::ToLocal(object)->SetAccessorProperty(
1485  Utils::ToLocal(name), Utils::ToLocal(getter_func),
1486  Utils::ToLocal(setter_func), attributes);
1487 }
1488 
1489 // Assigns a dummy instance template to the given constructor function. Used to
1490 // make sure the implicit receivers for the constructors in this file have an
1491 // instance type different from the internal one, they allocate the resulting
1492 // object explicitly and ignore implicit receiver.
1493 void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
1494  Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
1495  FunctionTemplateInfo::SetInstanceTemplate(
1496  isolate, handle(fun->shared()->get_api_func_data(), isolate),
1497  instance_template);
1498 }
1499 
1500 // static
1501 void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
1502  Handle<JSGlobalObject> global = isolate->global_object();
1503  Handle<Context> context(global->native_context(), isolate);
1504  // Install the JS API once only.
1505  Object* prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
1506  if (!prev->IsUndefined(isolate)) {
1507  DCHECK(prev->IsJSFunction());
1508  return;
1509  }
1510 
1511  Factory* factory = isolate->factory();
1512 
1513  // Setup WebAssembly
1514  Handle<String> name = v8_str(isolate, "WebAssembly");
1515  NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
1516  name, isolate->strict_function_map(), LanguageMode::kStrict);
1517  Handle<JSFunction> cons = factory->NewFunction(args);
1518  JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
1519  Handle<JSObject> webassembly = factory->NewJSObject(cons, TENURED);
1520  PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
1521 
1522  PropertyAttributes ro_attributes =
1523  static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
1524  JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
1525  name, ro_attributes);
1526  InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
1527  InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
1528  InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
1529 
1530  if (isolate->wasm_streaming_callback() != nullptr) {
1531  InstallFunc(isolate, webassembly, "compileStreaming",
1532  WebAssemblyCompileStreaming, 1);
1533  InstallFunc(isolate, webassembly, "instantiateStreaming",
1534  WebAssemblyInstantiateStreaming, 1);
1535  }
1536 
1537  // Expose the API on the global object if configured to do so.
1538  if (exposed_on_global_object) {
1539  JSObject::AddProperty(isolate, global, name, webassembly, attributes);
1540  }
1541 
1542  // Setup Module
1543  Handle<JSFunction> module_constructor =
1544  InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
1545  context->set_wasm_module_constructor(*module_constructor);
1546  SetDummyInstanceTemplate(isolate, module_constructor);
1547  JSFunction::EnsureHasInitialMap(module_constructor);
1548  Handle<JSObject> module_proto(
1549  JSObject::cast(module_constructor->instance_prototype()), isolate);
1550  i::Handle<i::Map> module_map =
1551  isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
1552  JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
1553  InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
1554  1);
1555  InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
1556  1);
1557  InstallFunc(isolate, module_constructor, "customSections",
1558  WebAssemblyModuleCustomSections, 2);
1559  JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
1560  v8_str(isolate, "WebAssembly.Module"), ro_attributes);
1561 
1562  // Setup Instance
1563  Handle<JSFunction> instance_constructor =
1564  InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
1565  context->set_wasm_instance_constructor(*instance_constructor);
1566  SetDummyInstanceTemplate(isolate, instance_constructor);
1567  JSFunction::EnsureHasInitialMap(instance_constructor);
1568  Handle<JSObject> instance_proto(
1569  JSObject::cast(instance_constructor->instance_prototype()), isolate);
1570  i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
1571  i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
1572  JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
1573  InstallGetter(isolate, instance_proto, "exports",
1574  WebAssemblyInstanceGetExports);
1575  JSObject::AddProperty(isolate, instance_proto,
1576  factory->to_string_tag_symbol(),
1577  v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
1578 
1579  // Setup Table
1580  Handle<JSFunction> table_constructor =
1581  InstallFunc(isolate, webassembly, "Table", WebAssemblyTable, 1);
1582  context->set_wasm_table_constructor(*table_constructor);
1583  SetDummyInstanceTemplate(isolate, table_constructor);
1584  JSFunction::EnsureHasInitialMap(table_constructor);
1585  Handle<JSObject> table_proto(
1586  JSObject::cast(table_constructor->instance_prototype()), isolate);
1587  i::Handle<i::Map> table_map =
1588  isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
1589  JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
1590  InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
1591  InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
1592  InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
1593  InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
1594  JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
1595  v8_str(isolate, "WebAssembly.Table"), ro_attributes);
1596 
1597  // Setup Memory
1598  Handle<JSFunction> memory_constructor =
1599  InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory, 1);
1600  context->set_wasm_memory_constructor(*memory_constructor);
1601  SetDummyInstanceTemplate(isolate, memory_constructor);
1602  JSFunction::EnsureHasInitialMap(memory_constructor);
1603  Handle<JSObject> memory_proto(
1604  JSObject::cast(memory_constructor->instance_prototype()), isolate);
1605  i::Handle<i::Map> memory_map =
1606  isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
1607  JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
1608  InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
1609  InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
1610  JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
1611  v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
1612 
1613  // The context is not set up completely yet. That's why we cannot use
1614  // {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
1615  auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1616 
1617  // Setup Global
1618  if (enabled_features.mut_global) {
1619  Handle<JSFunction> global_constructor =
1620  InstallFunc(isolate, webassembly, "Global", WebAssemblyGlobal, 1);
1621  context->set_wasm_global_constructor(*global_constructor);
1622  SetDummyInstanceTemplate(isolate, global_constructor);
1623  JSFunction::EnsureHasInitialMap(global_constructor);
1624  Handle<JSObject> global_proto(
1625  JSObject::cast(global_constructor->instance_prototype()), isolate);
1626  i::Handle<i::Map> global_map = isolate->factory()->NewMap(
1627  i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
1628  JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
1629  InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
1630  InstallGetterSetter(isolate, global_proto, "value",
1631  WebAssemblyGlobalGetValue, WebAssemblyGlobalSetValue);
1632  JSObject::AddProperty(isolate, global_proto,
1633  factory->to_string_tag_symbol(),
1634  v8_str(isolate, "WebAssembly.Global"), ro_attributes);
1635  }
1636 
1637  // Setup Exception
1638  if (enabled_features.eh) {
1639  Handle<JSFunction> exception_constructor =
1640  InstallFunc(isolate, webassembly, "Exception", WebAssemblyException, 1);
1641  context->set_wasm_exception_constructor(*exception_constructor);
1642  SetDummyInstanceTemplate(isolate, exception_constructor);
1643  JSFunction::EnsureHasInitialMap(exception_constructor);
1644  Handle<JSObject> exception_proto(
1645  JSObject::cast(exception_constructor->instance_prototype()), isolate);
1646  i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
1647  i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
1648  JSFunction::SetInitialMap(exception_constructor, exception_map,
1649  exception_proto);
1650  }
1651 
1652  // Setup errors
1653  attributes = static_cast<PropertyAttributes>(DONT_ENUM);
1654  Handle<JSFunction> compile_error(
1655  isolate->native_context()->wasm_compile_error_function(), isolate);
1656  JSObject::AddProperty(isolate, webassembly,
1657  isolate->factory()->CompileError_string(),
1658  compile_error, attributes);
1659  Handle<JSFunction> link_error(
1660  isolate->native_context()->wasm_link_error_function(), isolate);
1661  JSObject::AddProperty(isolate, webassembly,
1662  isolate->factory()->LinkError_string(), link_error,
1663  attributes);
1664  Handle<JSFunction> runtime_error(
1665  isolate->native_context()->wasm_runtime_error_function(), isolate);
1666  JSObject::AddProperty(isolate, webassembly,
1667  isolate->factory()->RuntimeError_string(),
1668  runtime_error, attributes);
1669 }
1670 
1671 #undef ASSIGN
1672 #undef EXTRACT_THIS
1673 
1674 } // namespace internal
1675 } // namespace v8
void SetModuleCompiledCallback(ModuleCompiledCallback callback, intptr_t data)
Definition: wasm-js.cc:103
static V8_WARN_UNUSED_RESULT MaybeLocal< Resolver > New(Local< Context > context)
Definition: api.cc:7240
bool StringEquals(Local< String > str)
Definition: api.cc:6694
void OnBytesReceived(const uint8_t *bytes, size_t size)
Definition: wasm-js.cc:93
PropertyAttribute
Definition: v8.h:3132
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:251
STL namespace.
static MaybeLocal< Function > New(Local< Context > context, FunctionCallback callback, Local< Value > data=Local< Value >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect)
Definition: api.cc:4919
static std::shared_ptr< WasmStreaming > Unpack(Isolate *isolate, Local< Value > value)
Definition: wasm-js.cc:113
Definition: v8.h:85
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
Definition: v8.h:347
void(* ModuleCompiledCallback)(intptr_t data, Local< WasmCompiledModule > compiled_module)
Definition: v8.h:4407
Definition: libplatform.h:13
static Local< ObjectTemplate > New(Isolate *isolate, Local< FunctionTemplate > constructor=Local< FunctionTemplate >())
Definition: api.cc:1616
V8_INLINE Local< T > ToLocalChecked()
Definition: v8.h:9402
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect)
Definition: api.cc:1417
void Abort(MaybeLocal< Value > exception)
Definition: wasm-js.cc:99
bool SetCompiledModuleBytes(const uint8_t *bytes, size_t size)
Definition: wasm-js.cc:108