1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/api-natives.h"
613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/api.h"
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-js.h"
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-typer.h"
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-wasm-builder.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assert-scope.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/ast.h"
1213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/execution.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h"
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects.h"
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/parsing/parse-info.h"
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/module-decoder.h"
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-js.h"
2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/wasm/wasm-limits.h"
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-module.h"
24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/wasm/wasm-objects.h"
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-result.h"
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef uint8_t byte;
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochusing v8::internal::wasm::ErrorThrower;
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace {
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define RANGE_ERROR_MSG                                                        \
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  "Wasm compilation exceeds internal limits in this context for the provided " \
3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  "arguments"
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// TODO(wasm): move brand check to the respective types, and don't throw
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// in it, rather, use a provided ErrorThrower, or let caller handle it.
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) {
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!value->IsJSObject()) return false;
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value);
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym);
4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return has_brand.FromMaybe(false);
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym,
4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       ErrorThrower* thrower, const char* msg) {
5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return HasBrand(value, sym) ? true : (thrower->TypeError("%s", msg), false);
5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
53f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochi::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
54f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return isolate->factory()->NewStringFromAsciiChecked(str);
55f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
56f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochLocal<String> v8_str(Isolate* isolate, const char* str) {
57f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
58f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
59f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochi::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule(
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 1) {
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->TypeError("Argument 0 must be a WebAssembly.Module");
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {};
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args[0]),
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::handle(i_context->wasm_module_sym()), thrower,
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  "Argument 0 must be a WebAssembly.Module")) {
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {};
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Local<Object> module_obj = Local<Object>::Cast(args[0]);
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return i::Handle<i::WasmModuleObject>::cast(
7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      v8::Utils::OpenHandle(*module_obj));
7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsCompilationAllowed(i::Isolate* isolate, ErrorThrower* thrower,
8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          v8::Local<v8::Value> source, bool is_async) {
8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Allow caller to do one final check on thrower state, rather than
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // one at each step. No information is lost - failure reason is captured
8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // in the thrower state.
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower->error()) return false;
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  AllowWasmCompileCallback callback = isolate->allow_wasm_compile_callback();
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (callback != nullptr &&
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      !callback(reinterpret_cast<v8::Isolate*>(isolate), source, is_async)) {
9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->RangeError(RANGE_ERROR_MSG);
9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return false;
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return true;
9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsInstantiationAllowed(i::Isolate* isolate, ErrorThrower* thrower,
9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            v8::Local<v8::Value> module_or_bytes,
9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            i::MaybeHandle<i::JSReceiver> ffi, bool is_async) {
10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Allow caller to do one final check on thrower state, rather than
10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // one at each step. No information is lost - failure reason is captured
10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // in the thrower state.
10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower->error()) return false;
10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::MaybeLocal<v8::Value> v8_ffi;
10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!ffi.is_null()) {
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    v8_ffi = v8::Local<v8::Value>::Cast(Utils::ToLocal(ffi.ToHandleChecked()));
10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  AllowWasmInstantiateCallback callback =
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate->allow_wasm_instantiate_callback();
11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (callback != nullptr &&
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      !callback(reinterpret_cast<v8::Isolate*>(isolate), module_or_bytes,
11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                v8_ffi, is_async)) {
11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->RangeError(RANGE_ERROR_MSG);
11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return false;
11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return true;
11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochi::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 1) {
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->TypeError("Argument 0 must be a buffer source");
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return i::wasm::ModuleWireBytes(nullptr, nullptr);
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const byte* start = nullptr;
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t length = 0;
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Local<v8::Value> source = args[0];
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (source->IsArrayBuffer()) {
1303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // A raw array buffer was passed.
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
1323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ArrayBuffer::Contents contents = buffer->GetContents();
1333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    start = reinterpret_cast<const byte*>(contents.Data());
13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    length = contents.ByteLength();
13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (source->IsTypedArray()) {
1373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // A TypedArray was passed.
13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Local<TypedArray> array = Local<TypedArray>::Cast(source);
1393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Local<ArrayBuffer> buffer = array->Buffer();
1403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ArrayBuffer::Contents contents = buffer->GetContents();
1423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    start =
1443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset();
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    length = array->ByteLength();
1463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->TypeError("Argument 0 must be a buffer source");
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_IMPLIES(length, start != nullptr);
15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (length == 0) {
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->CompileError("BufferSource argument is empty");
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (length > i::wasm::kV8MaxWasmModuleSize) {
15462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
15562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        i::wasm::kV8MaxWasmModuleSize, length);
15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(titzer): use the handle as well?
15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return i::wasm::ModuleWireBytes(start, start + length);
160f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
16262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochi::MaybeHandle<i::JSReceiver> GetSecondArgumentAsImports(
16362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
16462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 2) return {};
16562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args[1]->IsUndefined()) return {};
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!args[1]->IsObject()) {
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower->TypeError("Argument 1 must be an object");
16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {};
170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Local<Object> obj = Local<Object>::Cast(args[1]);
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
17313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
17562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.compile(bytes) -> Promise
17613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
17713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
17913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(isolate);
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
18113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Local<v8::Promise::Resolver> resolver;
18413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return_value.Set(resolver->GetPromise());
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto bytes = GetFirstArgumentAsBytes(args, &thrower);
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!IsCompilationAllowed(i_isolate, &thrower, args[0], true)) {
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(!thrower.error());
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise());
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::wasm::AsyncCompile(i_isolate, promise, bytes);
19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.validate(bytes) -> bool
199f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
200f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::Isolate* isolate = args.GetIsolate();
20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
202f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  HandleScope scope(isolate);
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.validate()");
204f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto bytes = GetFirstArgumentAsBytes(args, &thrower);
206f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
207f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!thrower.error() &&
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::wasm::SyncValidate(reinterpret_cast<i::Isolate*>(isolate), &thrower,
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            bytes)) {
211f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return_value.Set(v8::True(isolate));
212f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (thrower.wasm_error()) thrower.Reify();  // Clear error.
214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return_value.Set(v8::False(isolate));
215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
217f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// new WebAssembly.Module(bytes) -> WebAssembly.Module
21913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
22013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
22162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
22213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(isolate);
22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Module()");
22413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto bytes = GetFirstArgumentAsBytes(args, &thrower);
22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!IsCompilationAllowed(i_isolate, &thrower, args[0], false)) return;
22762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(!thrower.error());
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::MaybeHandle<i::Object> module_obj =
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::wasm::SyncCompile(i_isolate, &thrower, bytes);
23113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (module_obj.is_null()) return;
23213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
23513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
23613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Module.imports(module) -> Array<Import>
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(args.GetIsolate());
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
24462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) return;
24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.GetReturnValue().Set(Utils::ToLocal(imports));
24862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Module.exports(module) -> Array<Export>
25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(args.GetIsolate());
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
25662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
25762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) return;
25962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.GetReturnValue().Set(Utils::ToLocal(exports));
26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Module.customSections(module, name) -> Array<Section>
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WebAssemblyModuleCustomSections(
26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(args.GetIsolate());
26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()");
27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) return;
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 2) {
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError("Argument 1 must be a string");
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Object> name = Utils::OpenHandle(*args[1]);
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!name->IsString()) {
28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError("Argument 1 must be a string");
28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto custom_sections =
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 i::Handle<i::String>::cast(name), &thrower);
28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) return;
28962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
29062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(args.GetIsolate());
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) return;
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports,
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              false)) {
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(!thrower.error());
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate(
31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports,
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::MaybeHandle<i::JSArrayBuffer>());
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (instance_object.is_null()) return;
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked()));
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.instantiate(bytes, imports) ->
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch//     {module: WebAssembly.Module, instance: WebAssembly.Instance}
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::Local<v8::Promise::Resolver> resolver;
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return_value.Set(resolver->GetPromise());
33362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 1) {
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError(
33662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        "Argument 0 must be provided and must be either a buffer source or a "
33762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        "WebAssembly.Module object");
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return;
340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]);
34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!first_arg->IsJSObject()) {
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError(
34562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        "Argument 0 must be a buffer source or a WebAssembly.Module object");
34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
34762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (thrower.error()) {
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports,
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              true)) {
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return;
359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise());
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) {
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto module_object = GetFirstArgumentAsModule(args, &thrower);
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    i::wasm::AsyncInstantiate(i_isolate, promise,
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              module_object.ToHandleChecked(), maybe_imports);
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // WebAssembly.instantiate(bytes, imports) -> {module, instance}
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto bytes = GetFirstArgumentAsBytes(args, &thrower);
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (thrower.error()) {
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return;
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    i::wasm::AsyncCompileAndInstantiate(i_isolate, promise, bytes,
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                        maybe_imports);
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
378f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochbool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                        Local<Context> context, Local<v8::Object> object,
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        Local<String> property, int* result,
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        int64_t lower_bound, uint64_t upper_bound) {
382f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::Local<v8::Value> value;
384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (maybe.ToLocal(&value)) {
385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    int64_t number;
386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!value->IntegerValue(context).To(&number)) return false;
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (number < lower_bound) {
388f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      thrower->RangeError("Property value %" PRId64
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          " is below the lower bound %" PRIx64,
390f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                          number, lower_bound);
391f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return false;
392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
393f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (number > static_cast<int64_t>(upper_bound)) {
394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      thrower->RangeError("Property value %" PRId64
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          " is above the upper bound %" PRIu64,
396f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                          number, upper_bound);
397f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return false;
398f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
399f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    *result = static_cast<int>(number);
400f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return true;
401f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
402f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return false;
403f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
404f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// new WebAssembly.Table(args) -> WebAssembly.Table
406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
407f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::Isolate* isolate = args.GetIsolate();
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
409f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  HandleScope scope(isolate);
41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Module()");
411f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (args.Length() < 1 || !args[0]->IsObject()) {
412f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    thrower.TypeError("Argument 0 must be a table descriptor");
413f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
414f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
415f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<Context> context = isolate->GetCurrentContext();
416f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
417f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The descriptor's 'element'.
418f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
419f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    v8::MaybeLocal<v8::Value> maybe =
420f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        descriptor->Get(context, v8_str(isolate, "element"));
421f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    v8::Local<v8::Value> value;
422f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!maybe.ToLocal(&value)) return;
423f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    v8::Local<v8::String> string;
424f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!value->ToString(context).ToLocal(&string)) return;
425f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool equal;
426f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return;
427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!equal) {
428f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
429f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return;
430f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
431f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
432f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The descriptor's 'initial'.
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int initial = 0;
434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
435f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                          v8_str(isolate, "initial"), &initial, 0,
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          i::FLAG_wasm_max_table_size)) {
437f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
438f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
439f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The descriptor's 'maximum'.
44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int maximum = -1;
441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<String> maximum_key = v8_str(isolate, "maximum");
442f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
443f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
44662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            &maximum, initial,
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            i::wasm::kSpecMaxWasmTableSize)) {
448f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return;
449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
450f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
451f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
452c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::FixedArray> fixed_array;
453f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::Handle<i::JSObject> table_obj =
454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array);
455f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
456f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return_value.Set(Utils::ToLocal(table_obj));
457f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
458f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
459f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
460f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::Isolate* isolate = args.GetIsolate();
46162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
462f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  HandleScope scope(isolate);
46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (args.Length() < 1 || !args[0]->IsObject()) {
465c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    thrower.TypeError("Argument 0 must be a memory descriptor");
466f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
467f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
468f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<Context> context = isolate->GetCurrentContext();
469f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
470f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The descriptor's 'initial'.
47162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int initial = 0;
472f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          v8_str(isolate, "initial"), &initial, 0,
47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          i::FLAG_wasm_max_mem_pages)) {
475f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
476f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
477f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The descriptor's 'maximum'.
47862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int maximum = -1;
479f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<String> maximum_key = v8_str(isolate, "maximum");
480f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
481f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
48262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
483f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            &maximum, initial,
48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            i::wasm::kSpecMaxWasmMemoryPages)) {
486f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return;
487f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
488f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
489f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) *
490f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                static_cast<size_t>(initial);
49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSArrayBuffer> buffer =
49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages);
49362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (buffer.is_null()) {
49462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError("could not allocate memory");
49562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
49662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
49762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSObject> memory_obj =
49862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::WasmMemoryObject::New(i_isolate, buffer, maximum);
499c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
500f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
501c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
502f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyTableGetLength(
503f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
504c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
50562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
50662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
50762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
509c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
51062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
51162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
512c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  "Receiver is not a WebAssembly.Table")) {
513c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
514c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
515c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  auto receiver =
516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  args.GetReturnValue().Set(
518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      v8::Number::New(isolate, receiver->current_length()));
519f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
520c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
52162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Table.grow(num) -> num
522f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
523c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
52662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
527c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
52962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
53062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  "Receiver is not a WebAssembly.Table")) {
532c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
533c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
534c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
535c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  auto receiver =
536c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
53762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate);
538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int old_size = old_array->length();
539c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int64_t new_size64 = 0;
540c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) {
541c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  new_size64 += old_size;
544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
54562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int64_t max_size64 = receiver->maximum_length();
54662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (max_size64 < 0 ||
54762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) {
54862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    max_size64 = i::FLAG_wasm_max_table_size;
54962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
55062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (new_size64 < old_size || new_size64 > max_size64) {
55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError(new_size64 < old_size ? "trying to shrink table"
55362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                             : "maximum table size exceeded");
554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
55662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int new_size = static_cast<int>(new_size64);
55862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::WasmTableObject::Grow(i_isolate, receiver,
55962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           static_cast<uint32_t>(new_size - old_size));
560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (new_size != old_size) {
562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    i::Handle<i::FixedArray> new_array =
563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        i_isolate->factory()->NewFixedArray(new_size);
564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i));
565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    i::Object* null = i_isolate->heap()->null_value();
566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (int i = old_size; i < new_size; ++i) new_array->set(i, null);
567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    receiver->set_functions(*new_array);
568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(gdeepti): use weak links for instances
57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return_value.Set(old_size);
573f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
574c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
57562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Table.get(num) -> JSFunction
576f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
577c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
57862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
57962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
58062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
581c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
58362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
58462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
585c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  "Receiver is not a WebAssembly.Table")) {
586c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
587c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  auto receiver =
590c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
59162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int i = 0;
593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return;
594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (i < 0 || i >= array->length()) {
59662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError("index out of bounds");
597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
598c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Object> value(array->get(i), i_isolate);
601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return_value.Set(Utils::ToLocal(value));
602f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
60462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Table.set(num, JSFunction)
605f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
60862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
60962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
61262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
61362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  "Receiver is not a WebAssembly.Table")) {
615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (args.Length() < 2) {
61862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError("Argument 1 must be null or a function");
619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Object> value = Utils::OpenHandle(*args[1]);
622c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (!value->IsNull(i_isolate) &&
623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      (!value->IsJSFunction() ||
624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch       i::Handle<i::JSFunction>::cast(value)->code()->kind() !=
625c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch           i::Code::JS_TO_WASM_FUNCTION)) {
62662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError("Argument 1 must be null or a WebAssembly function");
627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
628c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  auto receiver =
631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
63262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int i;
634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (!args[0]->Int32Value(context).To(&i)) return;
635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (i < 0 || i >= array->length()) {
63662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError("index out of bounds");
637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
64062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(),
641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                           i_isolate);
642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (value->IsNull(i_isolate)) {
643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                  i::Handle<i::JSFunction>::null());
645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                  i::Handle<i::JSFunction>::cast(value));
648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::FixedArray>::cast(array)->set(i, *value);
651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Memory.grow(num) -> num
654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
65762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_memory_sym()), &thrower,
663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  "Receiver is not a WebAssembly.Memory")) {
664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
66662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int64_t delta_size = 0;
66762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) {
66862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.TypeError("Argument 0 required, must be numeric value of pages");
669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::WasmMemoryObject> receiver =
67262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This()));
67362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int64_t max_size64 = receiver->maximum_pages();
67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (max_size64 < 0 ||
67562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) {
67662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    max_size64 = i::FLAG_wasm_max_mem_pages;
67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
67862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer());
67962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t old_size =
68062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages;
68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int64_t new_size64 = old_size + delta_size;
68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) {
68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError(new_size64 < old_size ? "trying to shrink memory"
68462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                             : "maximum memory size exceeded");
685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
68762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int32_t ret = i::wasm::GrowWebAssemblyMemory(
68862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i_isolate, receiver, static_cast<uint32_t>(delta_size));
68962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (ret == -1) {
69062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    thrower.RangeError("Unable to grow instance memory.");
691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return;
692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return_value.Set(ret);
695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
696c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
69762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// WebAssembly.Memory.buffer -> ArrayBuffer
698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid WebAssemblyMemoryGetBuffer(
699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
700f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::Isolate* isolate = args.GetIsolate();
70162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
70262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
70362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Local<Context> context = isolate->GetCurrentContext();
705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
70662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!BrandCheck(Utils::OpenHandle(*args.This()),
70762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  i::Handle<i::Symbol>(i_context->wasm_memory_sym()), &thrower,
708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  "Receiver is not a WebAssembly.Memory")) {
709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
71162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::WasmMemoryObject> receiver =
71262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This()));
71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Object> buffer(receiver->buffer(), i_isolate);
714f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(buffer->IsJSArrayBuffer());
715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
716f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return_value.Set(Utils::ToLocal(buffer));
717f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TODO(titzer): we use the API to create the function template because the
721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// internal guts are too ugly to replicate here.
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      FunctionCallback func) {
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
72662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  templ->ReadOnlyPrototype();
72762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return v8::Utils::OpenHandle(*templ);
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
732f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHandle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
73362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               const char* str, FunctionCallback func,
73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               int length = 0) {
735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<String> name = v8_str(isolate, str);
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> function =
738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ApiNatives::InstantiateFunction(temp).ToHandleChecked();
73962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::SetName(function, name, isolate->factory()->empty_string());
74062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  function->shared()->set_length(length);
74162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSObject::AddProperty(object, name, function, attributes);
74313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return function;
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHandle<JSFunction> InstallGetter(Isolate* isolate, Handle<JSObject> object,
747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                 const char* str, FunctionCallback func) {
748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<String> name = v8_str(isolate, str);
749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> function =
751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      ApiNatives::InstantiateFunction(temp).ToHandleChecked();
752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  v8::PropertyAttribute attributes =
75362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      static_cast<v8::PropertyAttribute>(v8::DontEnum);
754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                              Utils::ToLocal(function),
756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                              Local<Function>(), attributes);
757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return function;
758f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
759f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
76062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid WasmJs::Install(Isolate* isolate) {
76162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSGlobalObject> global = isolate->global_object();
76262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Context> context(global->native_context(), isolate);
76362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(titzer): once FLAG_expose_wasm is gone, this should become a DCHECK.
76462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) return;
76562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
76662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Install Maps.
76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
76862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(titzer): Also make one for strict mode functions?
76962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstanceType instance_type = prev_map->instance_type();
77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int internal_fields = JSObject::GetInternalFieldCount(*prev_map);
77362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CHECK_EQ(0, internal_fields);
77462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int pre_allocated =
77562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
77662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int instance_size = 0;
77762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int in_object_properties = 0;
77862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int wasm_internal_fields = internal_fields + 1  // module instance object
77962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      + 1                  // function arity
78062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      + 1;                 // function signature
78162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::CalculateInstanceSizeHelper(instance_type, wasm_internal_fields,
78262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          0, &instance_size,
78362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          &in_object_properties);
78462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
78562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int unused_property_fields = in_object_properties - pre_allocated;
78662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Map> map = Map::CopyInitialMap(
78762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      prev_map, instance_size, in_object_properties, unused_property_fields);
78862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
78962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  context->set_wasm_function_map(*map);
79062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
79162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Install symbols.
792f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
793f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Factory* factory = isolate->factory();
794f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Create private symbols.
795f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<Symbol> module_sym = factory->NewPrivateSymbol();
796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_module_sym(*module_sym);
797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
798f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<Symbol> instance_sym = factory->NewPrivateSymbol();
799f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_instance_sym(*instance_sym);
800f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
801f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<Symbol> table_sym = factory->NewPrivateSymbol();
802f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_table_sym(*table_sym);
803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<Symbol> memory_sym = factory->NewPrivateSymbol();
805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_memory_sym(*memory_sym);
806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
80762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Install the JS API.
80862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
80962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Setup WebAssembly
810f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<String> name = v8_str(isolate, "WebAssembly");
811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> cons = factory->NewFunction(name);
812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  JSFunction::SetInstancePrototype(
813f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      cons, Handle<Object>(context->initial_object_prototype(), isolate));
814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  cons->shared()->set_instance_class_name(*name);
815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<JSObject> webassembly = factory->NewJSObject(cons, TENURED);
816f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  JSObject::AddProperty(global, name, webassembly, attributes);
81862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  PropertyAttributes ro_attributes =
81962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
82062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(webassembly, factory->to_string_tag_symbol(),
82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        v8_str(isolate, "WebAssembly"), ro_attributes);
82262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
82362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
82462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Setup Module
827f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> module_constructor =
82862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
829f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_module_constructor(*module_constructor);
830f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSObject> module_proto =
831f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      factory->NewJSObject(module_constructor, TENURED);
83262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Map> module_map = isolate->factory()->NewMap(
83362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             WasmModuleObject::kFieldCount * i::kPointerSize);
83562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
83662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
83762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              1);
83862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
83962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              1);
84062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, module_constructor, "customSections",
84162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              WebAssemblyModuleCustomSections, 2);
842f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  JSObject::AddProperty(module_proto, isolate->factory()->constructor_string(),
843f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                        module_constructor, DONT_ENUM);
84462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(module_proto, factory->to_string_tag_symbol(),
84562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        v8_str(isolate, "WebAssembly.Module"), ro_attributes);
846f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
847f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Setup Instance
848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> instance_constructor =
84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
850f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_instance_constructor(*instance_constructor);
85162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSObject> instance_proto =
85262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      factory->NewJSObject(instance_constructor, TENURED);
85362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
85462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
85562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             WasmInstanceObject::kFieldCount * i::kPointerSize);
85662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
85762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(instance_proto,
85862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        isolate->factory()->constructor_string(),
85962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        instance_constructor, DONT_ENUM);
86062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(instance_proto, factory->to_string_tag_symbol(),
86162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
862f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
863f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Setup Table
864f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> table_constructor =
86562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      InstallFunc(isolate, webassembly, "Table", WebAssemblyTable, 1);
866f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_table_constructor(*table_constructor);
867f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSObject> table_proto =
868f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      factory->NewJSObject(table_constructor, TENURED);
86962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Map> table_map = isolate->factory()->NewMap(
87062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             WasmTableObject::kFieldCount * i::kPointerSize);
87262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
873f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(),
874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                        table_constructor, DONT_ENUM);
875f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
87662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
87762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
87862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
87962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(table_proto, factory->to_string_tag_symbol(),
88062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        v8_str(isolate, "WebAssembly.Table"), ro_attributes);
881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Setup Memory
883f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSFunction> memory_constructor =
88462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory, 1);
885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  context->set_wasm_memory_constructor(*memory_constructor);
886f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<JSObject> memory_proto =
887f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      factory->NewJSObject(memory_constructor, TENURED);
88862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  i::Handle<i::Map> memory_map = isolate->factory()->NewMap(
88962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             WasmMemoryObject::kFieldCount * i::kPointerSize);
89162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
892f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(),
893f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                        memory_constructor, DONT_ENUM);
89462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
89662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(memory_proto, factory->to_string_tag_symbol(),
89762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
898c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Setup errors
90062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  attributes = static_cast<PropertyAttributes>(DONT_ENUM);
901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<JSFunction> compile_error(
902c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate->native_context()->wasm_compile_error_function());
903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  JSObject::AddProperty(webassembly, isolate->factory()->CompileError_string(),
904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                        compile_error, attributes);
90562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSFunction> link_error(
90662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate->native_context()->wasm_link_error_function());
90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(),
90862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        link_error, attributes);
909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<JSFunction> runtime_error(
910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate->native_context()->wasm_runtime_error_function());
911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(),
912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                        runtime_error, attributes);
913f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
914f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochbool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) {
916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return HasBrand(value, symbol);
918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
920c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochbool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
921c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return HasBrand(value, symbol);
923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
926