Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/wasm/wasm-js.h"
6 :
7 : #include <string>
8 :
9 : #include "src/api-inl.h"
10 : #include "src/api-natives.h"
11 : #include "src/assert-scope.h"
12 : #include "src/ast/ast.h"
13 : #include "src/base/overflowing-math.h"
14 : #include "src/execution.h"
15 : #include "src/handles.h"
16 : #include "src/heap/factory.h"
17 : #include "src/isolate.h"
18 : #include "src/objects-inl.h"
19 : #include "src/objects/js-promise-inl.h"
20 : #include "src/objects/templates.h"
21 : #include "src/parsing/parse-info.h"
22 : #include "src/task-utils.h"
23 : #include "src/trap-handler/trap-handler.h"
24 : #include "src/v8.h"
25 : #include "src/wasm/streaming-decoder.h"
26 : #include "src/wasm/wasm-engine.h"
27 : #include "src/wasm/wasm-limits.h"
28 : #include "src/wasm/wasm-memory.h"
29 : #include "src/wasm/wasm-objects-inl.h"
30 : #include "src/wasm/wasm-serialization.h"
31 :
32 : using v8::internal::wasm::ErrorThrower;
33 :
34 : namespace v8 {
35 :
36 48 : class WasmStreaming::WasmStreamingImpl {
37 : public:
38 24 : WasmStreamingImpl(
39 : Isolate* isolate,
40 : std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
41 24 : : isolate_(isolate), resolver_(std::move(resolver)) {
42 24 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
43 24 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
44 72 : streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
45 : i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
46 : resolver_);
47 24 : }
48 :
49 : void OnBytesReceived(const uint8_t* bytes, size_t size) {
50 8 : streaming_decoder_->OnBytesReceived(i::VectorOf(bytes, size));
51 : }
52 8 : void Finish() { streaming_decoder_->Finish(); }
53 :
54 8 : void Abort(MaybeLocal<Value> exception) {
55 8 : i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
56 8 : streaming_decoder_->Abort();
57 :
58 : // If no exception value is provided, we do not reject the promise. This can
59 : // happen when streaming compilation gets aborted when no script execution
60 : // is allowed anymore, e.g. when a browser tab gets refreshed.
61 8 : if (exception.IsEmpty()) return;
62 :
63 : resolver_->OnCompilationFailed(
64 8 : Utils::OpenHandle(*exception.ToLocalChecked()));
65 : }
66 :
67 0 : bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
68 0 : if (!i::wasm::IsSupportedVersion({bytes, size})) return false;
69 0 : return streaming_decoder_->SetCompiledModuleBytes({bytes, size});
70 : }
71 :
72 0 : void SetClient(std::shared_ptr<Client> client) {
73 : // There are no other event notifications so just pass client to decoder.
74 : // Wrap the client with a callback to trigger the callback in a new
75 : // foreground task.
76 0 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
77 0 : v8::Platform* platform = i::V8::GetCurrentPlatform();
78 : std::shared_ptr<TaskRunner> foreground_task_runner =
79 0 : platform->GetForegroundTaskRunner(isolate_);
80 0 : streaming_decoder_->SetModuleCompiledCallback(
81 0 : [client, i_isolate, foreground_task_runner](
82 0 : const std::shared_ptr<i::wasm::NativeModule>& native_module) {
83 0 : foreground_task_runner->PostTask(
84 0 : i::MakeCancelableTask(i_isolate, [client, native_module] {
85 0 : client->OnModuleCompiled(Utils::Convert(native_module));
86 0 : }));
87 0 : });
88 0 : }
89 :
90 : private:
91 : Isolate* const isolate_;
92 : std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
93 : std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
94 : };
95 :
96 0 : WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl)
97 0 : : impl_(std::move(impl)) {}
98 :
99 : // The destructor is defined here because we have a unique_ptr with forward
100 : // declaration.
101 : WasmStreaming::~WasmStreaming() = default;
102 :
103 8 : void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
104 : impl_->OnBytesReceived(bytes, size);
105 8 : }
106 :
107 16 : void WasmStreaming::Finish() { impl_->Finish(); }
108 :
109 8 : void WasmStreaming::Abort(MaybeLocal<Value> exception) {
110 8 : impl_->Abort(exception);
111 8 : }
112 :
113 0 : bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
114 0 : return impl_->SetCompiledModuleBytes(bytes, size);
115 : }
116 :
117 0 : void WasmStreaming::SetClient(std::shared_ptr<Client> client) {
118 0 : impl_->SetClient(client);
119 0 : }
120 :
121 : // static
122 20 : std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
123 : Local<Value> value) {
124 : i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate));
125 : auto managed =
126 : i::Handle<i::Managed<WasmStreaming>>::cast(Utils::OpenHandle(*value));
127 20 : return managed->get();
128 : }
129 :
130 : namespace {
131 :
132 : #define ASSIGN(type, var, expr) \
133 : Local<type> var; \
134 : do { \
135 : if (!expr.ToLocal(&var)) { \
136 : DCHECK(i_isolate->has_scheduled_exception()); \
137 : return; \
138 : } else { \
139 : DCHECK(!i_isolate->has_scheduled_exception()); \
140 : } \
141 : } while (false)
142 :
143 : // Like an ErrorThrower, but turns all pending exceptions into scheduled
144 : // exceptions when going out of scope. Use this in API methods.
145 : // Note that pending exceptions are not necessarily created by the ErrorThrower,
146 : // but e.g. by the wasm start function. There might also be a scheduled
147 : // exception, created by another API call (e.g. v8::Object::Get). But there
148 : // should never be both pending and scheduled exceptions.
149 : class ScheduledErrorThrower : public ErrorThrower {
150 : public:
151 : ScheduledErrorThrower(i::Isolate* isolate, const char* context)
152 : : ErrorThrower(isolate, context) {}
153 :
154 : ~ScheduledErrorThrower();
155 : };
156 :
157 107740740 : ScheduledErrorThrower::~ScheduledErrorThrower() {
158 : // There should never be both a pending and a scheduled exception.
159 : DCHECK(!isolate()->has_scheduled_exception() ||
160 : !isolate()->has_pending_exception());
161 : // Don't throw another error if there is already a scheduled error.
162 53870370 : if (isolate()->has_scheduled_exception()) {
163 1808 : Reset();
164 53868562 : } else if (isolate()->has_pending_exception()) {
165 48 : Reset();
166 48 : isolate()->OptionalRescheduleException(false);
167 53868514 : } else if (error()) {
168 47376 : isolate()->ScheduleThrow(*Reify());
169 : }
170 53870370 : }
171 :
172 : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
173 2141838 : return isolate->factory()->NewStringFromAsciiChecked(str);
174 : }
175 : Local<String> v8_str(Isolate* isolate, const char* str) {
176 : return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
177 : }
178 :
179 : #define GET_FIRST_ARGUMENT_AS(Type) \
180 : i::MaybeHandle<i::Wasm##Type##Object> GetFirstArgumentAs##Type( \
181 : const v8::FunctionCallbackInfo<v8::Value>& args, \
182 : ErrorThrower* thrower) { \
183 : i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]); \
184 : if (!arg0->IsWasm##Type##Object()) { \
185 : thrower->TypeError("Argument 0 must be a WebAssembly." #Type); \
186 : return {}; \
187 : } \
188 : Local<Object> obj = Local<Object>::Cast(args[0]); \
189 : return i::Handle<i::Wasm##Type##Object>::cast( \
190 : v8::Utils::OpenHandle(*obj)); \
191 : }
192 :
193 389875 : GET_FIRST_ARGUMENT_AS(Module)
194 208 : GET_FIRST_ARGUMENT_AS(Memory)
195 256 : GET_FIRST_ARGUMENT_AS(Table)
196 232 : GET_FIRST_ARGUMENT_AS(Global)
197 :
198 : #undef GET_FIRST_ARGUMENT_AS
199 :
200 282082 : i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
201 : const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower,
202 : bool* is_shared) {
203 : const uint8_t* start = nullptr;
204 : size_t length = 0;
205 : v8::Local<v8::Value> source = args[0];
206 282082 : if (source->IsArrayBuffer()) {
207 : // A raw array buffer was passed.
208 : Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
209 254176 : ArrayBuffer::Contents contents = buffer->GetContents();
210 :
211 : start = reinterpret_cast<const uint8_t*>(contents.Data());
212 : length = contents.ByteLength();
213 254176 : *is_shared = buffer->IsSharedArrayBuffer();
214 27911 : } else if (source->IsTypedArray()) {
215 : // A TypedArray was passed.
216 : Local<TypedArray> array = Local<TypedArray>::Cast(source);
217 27432 : Local<ArrayBuffer> buffer = array->Buffer();
218 :
219 27433 : ArrayBuffer::Contents contents = buffer->GetContents();
220 :
221 : start =
222 27435 : reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
223 27439 : length = array->ByteLength();
224 27442 : *is_shared = buffer->IsSharedArrayBuffer();
225 : } else {
226 480 : thrower->TypeError("Argument 0 must be a buffer source");
227 : }
228 : DCHECK_IMPLIES(length, start != nullptr);
229 282099 : if (length == 0) {
230 780 : thrower->CompileError("BufferSource argument is empty");
231 : }
232 282099 : if (length > i::wasm::kV8MaxWasmModuleSize) {
233 : thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
234 0 : i::wasm::kV8MaxWasmModuleSize, length);
235 : }
236 282099 : if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
237 281295 : return i::wasm::ModuleWireBytes(start, start + length);
238 : }
239 :
240 131782 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
241 : ErrorThrower* thrower) {
242 131782 : if (arg->IsUndefined()) return {};
243 :
244 124754 : if (!arg->IsObject()) {
245 240 : thrower->TypeError("Argument 1 must be an object");
246 240 : return {};
247 : }
248 : Local<Object> obj = Local<Object>::Cast(arg);
249 124516 : return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
250 : }
251 :
252 : namespace {
253 : // This class resolves the result of WebAssembly.compile. It just places the
254 : // compilation result in the supplied {promise}.
255 : class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
256 : public:
257 808 : AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
258 1616 : : promise_(isolate->global_handles()->Create(*promise)) {
259 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
260 808 : kGlobalPromiseHandle);
261 808 : }
262 :
263 1616 : ~AsyncCompilationResolver() override {
264 808 : i::GlobalHandles::Destroy(promise_.location());
265 784 : }
266 :
267 332 : void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
268 332 : if (finished_) return;
269 332 : finished_ = true;
270 : i::MaybeHandle<i::Object> promise_result =
271 332 : i::JSPromise::Resolve(promise_, result);
272 332 : CHECK_EQ(promise_result.is_null(),
273 : promise_->GetIsolate()->has_pending_exception());
274 : }
275 :
276 460 : void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
277 460 : if (finished_) return;
278 460 : finished_ = true;
279 : i::MaybeHandle<i::Object> promise_result =
280 460 : i::JSPromise::Reject(promise_, error_reason);
281 460 : CHECK_EQ(promise_result.is_null(),
282 : promise_->GetIsolate()->has_pending_exception());
283 : }
284 :
285 : private:
286 : static constexpr char kGlobalPromiseHandle[] =
287 : "AsyncCompilationResolver::promise_";
288 : bool finished_ = false;
289 : i::Handle<i::JSPromise> promise_;
290 : };
291 :
292 : constexpr char AsyncCompilationResolver::kGlobalPromiseHandle[];
293 :
294 : // This class resolves the result of WebAssembly.instantiate(module, imports).
295 : // It just places the instantiation result in the supplied {promise}.
296 : class InstantiateModuleResultResolver
297 : : public i::wasm::InstantiationResultResolver {
298 : public:
299 7319 : InstantiateModuleResultResolver(i::Isolate* isolate,
300 : i::Handle<i::JSPromise> promise)
301 14638 : : promise_(isolate->global_handles()->Create(*promise)) {
302 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
303 7319 : kGlobalPromiseHandle);
304 7319 : }
305 :
306 14638 : ~InstantiateModuleResultResolver() override {
307 7319 : i::GlobalHandles::Destroy(promise_.location());
308 7319 : }
309 :
310 112 : void OnInstantiationSucceeded(
311 : i::Handle<i::WasmInstanceObject> instance) override {
312 : i::MaybeHandle<i::Object> promise_result =
313 112 : i::JSPromise::Resolve(promise_, instance);
314 112 : CHECK_EQ(promise_result.is_null(),
315 : promise_->GetIsolate()->has_pending_exception());
316 112 : }
317 :
318 5371 : void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
319 : i::MaybeHandle<i::Object> promise_result =
320 5371 : i::JSPromise::Reject(promise_, error_reason);
321 5371 : CHECK_EQ(promise_result.is_null(),
322 : promise_->GetIsolate()->has_pending_exception());
323 5371 : }
324 :
325 : private:
326 : static constexpr char kGlobalPromiseHandle[] =
327 : "InstantiateModuleResultResolver::promise_";
328 : i::Handle<i::JSPromise> promise_;
329 : };
330 :
331 : constexpr char InstantiateModuleResultResolver::kGlobalPromiseHandle[];
332 :
333 : // This class resolves the result of WebAssembly.instantiate(bytes, imports).
334 : // For that it creates a new {JSObject} which contains both the provided
335 : // {WasmModuleObject} and the resulting {WebAssemblyInstanceObject} itself.
336 : class InstantiateBytesResultResolver
337 : : public i::wasm::InstantiationResultResolver {
338 : public:
339 1812 : InstantiateBytesResultResolver(i::Isolate* isolate,
340 : i::Handle<i::JSPromise> promise,
341 : i::Handle<i::WasmModuleObject> module)
342 : : isolate_(isolate),
343 : promise_(isolate_->global_handles()->Create(*promise)),
344 7248 : module_(isolate_->global_handles()->Create(*module)) {
345 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
346 1812 : kGlobalPromiseHandle);
347 : i::GlobalHandles::AnnotateStrongRetainer(module_.location(),
348 1812 : kGlobalModuleHandle);
349 1812 : }
350 :
351 3624 : ~InstantiateBytesResultResolver() override {
352 1812 : i::GlobalHandles::Destroy(promise_.location());
353 1812 : i::GlobalHandles::Destroy(module_.location());
354 1812 : }
355 :
356 1164 : void OnInstantiationSucceeded(
357 : i::Handle<i::WasmInstanceObject> instance) override {
358 : // The result is a JSObject with 2 fields which contain the
359 : // WasmInstanceObject and the WasmModuleObject.
360 : i::Handle<i::JSObject> result =
361 1164 : isolate_->factory()->NewJSObject(isolate_->object_function());
362 :
363 : i::Handle<i::String> instance_name =
364 1164 : isolate_->factory()
365 2328 : ->NewStringFromOneByte(i::StaticCharVector("instance"))
366 : .ToHandleChecked();
367 :
368 : i::Handle<i::String> module_name =
369 1164 : isolate_->factory()
370 2328 : ->NewStringFromOneByte(i::StaticCharVector("module"))
371 : .ToHandleChecked();
372 :
373 2328 : i::JSObject::AddProperty(isolate_, result, instance_name, instance,
374 1164 : i::NONE);
375 1164 : i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);
376 :
377 : i::MaybeHandle<i::Object> promise_result =
378 1164 : i::JSPromise::Resolve(promise_, result);
379 2328 : CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
380 1164 : }
381 :
382 648 : void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
383 : i::MaybeHandle<i::Object> promise_result =
384 648 : i::JSPromise::Reject(promise_, error_reason);
385 1296 : CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
386 648 : }
387 :
388 : private:
389 : static constexpr char kGlobalPromiseHandle[] =
390 : "InstantiateBytesResultResolver::promise_";
391 : static constexpr char kGlobalModuleHandle[] =
392 : "InstantiateBytesResultResolver::module_";
393 : i::Isolate* isolate_;
394 : i::Handle<i::JSPromise> promise_;
395 : i::Handle<i::WasmModuleObject> module_;
396 : };
397 :
398 : constexpr char InstantiateBytesResultResolver::kGlobalPromiseHandle[];
399 : constexpr char InstantiateBytesResultResolver::kGlobalModuleHandle[];
400 :
401 : // This class is the {CompilationResultResolver} for
402 : // WebAssembly.instantiate(bytes, imports). When compilation finishes,
403 : // {AsyncInstantiate} is started on the compilation result.
404 : class AsyncInstantiateCompileResultResolver
405 : : public i::wasm::CompilationResultResolver {
406 : public:
407 1836 : AsyncInstantiateCompileResultResolver(
408 : i::Isolate* isolate, i::Handle<i::JSPromise> promise,
409 : i::MaybeHandle<i::JSReceiver> maybe_imports)
410 : : isolate_(isolate),
411 : promise_(isolate_->global_handles()->Create(*promise)),
412 : maybe_imports_(maybe_imports.is_null()
413 : ? maybe_imports
414 744 : : isolate_->global_handles()->Create(
415 5508 : *maybe_imports.ToHandleChecked())) {
416 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
417 1836 : kGlobalPromiseHandle);
418 1836 : if (!maybe_imports_.is_null()) {
419 : i::GlobalHandles::AnnotateStrongRetainer(
420 744 : maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle);
421 : }
422 1836 : }
423 :
424 3672 : ~AsyncInstantiateCompileResultResolver() override {
425 1836 : i::GlobalHandles::Destroy(promise_.location());
426 1836 : if (!maybe_imports_.is_null()) {
427 744 : i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
428 : }
429 3672 : }
430 :
431 1812 : void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
432 1812 : if (finished_) return;
433 1812 : finished_ = true;
434 3624 : isolate_->wasm_engine()->AsyncInstantiate(
435 : isolate_,
436 3624 : base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
437 : result),
438 1812 : result, maybe_imports_);
439 : }
440 :
441 24 : void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
442 24 : if (finished_) return;
443 24 : finished_ = true;
444 : i::MaybeHandle<i::Object> promise_result =
445 24 : i::JSPromise::Reject(promise_, error_reason);
446 48 : CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
447 : }
448 :
449 : private:
450 : static constexpr char kGlobalPromiseHandle[] =
451 : "AsyncInstantiateCompileResultResolver::promise_";
452 : static constexpr char kGlobalImportsHandle[] =
453 : "AsyncInstantiateCompileResultResolver::module_";
454 : bool finished_ = false;
455 : i::Isolate* isolate_;
456 : i::Handle<i::JSPromise> promise_;
457 : i::MaybeHandle<i::JSReceiver> maybe_imports_;
458 : };
459 :
460 : constexpr char AsyncInstantiateCompileResultResolver::kGlobalPromiseHandle[];
461 : constexpr char AsyncInstantiateCompileResultResolver::kGlobalImportsHandle[];
462 :
463 976 : std::string ToString(const char* name) { return std::string(name); }
464 :
465 312 : std::string ToString(const i::Handle<i::String> name) {
466 1560 : return std::string("Property '") + name->ToCString().get() + "'";
467 : }
468 :
469 : // Web IDL: '[EnforceRange] unsigned long'
470 : // Previously called ToNonWrappingUint32 in the draft WebAssembly JS spec.
471 : // https://heycam.github.io/webidl/#EnforceRange
472 : template <typename T>
473 24972 : bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context,
474 : ErrorThrower* thrower, uint32_t* res) {
475 : double double_number;
476 :
477 49944 : if (!v->NumberValue(context).To(&double_number)) {
478 128 : thrower->TypeError("%s must be convertible to a number",
479 : ToString(argument_name).c_str());
480 64 : return false;
481 : }
482 24908 : if (!std::isfinite(double_number)) {
483 1152 : thrower->TypeError("%s must be convertible to a valid number",
484 : ToString(argument_name).c_str());
485 576 : return false;
486 : }
487 24332 : if (double_number < 0) {
488 736 : thrower->TypeError("%s must be non-negative",
489 : ToString(argument_name).c_str());
490 368 : return false;
491 : }
492 23964 : if (double_number > std::numeric_limits<uint32_t>::max()) {
493 560 : thrower->TypeError("%s must be in the unsigned long range",
494 : ToString(argument_name).c_str());
495 280 : return false;
496 : }
497 :
498 23684 : *res = static_cast<uint32_t>(double_number);
499 23684 : return true;
500 : }
501 : } // namespace
502 :
503 : // WebAssembly.compile(bytes) -> Promise
504 784 : void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
505 : v8::Isolate* isolate = args.GetIsolate();
506 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
507 :
508 1324 : HandleScope scope(isolate);
509 540 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
510 :
511 1568 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
512 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
513 : }
514 :
515 784 : Local<Context> context = isolate->GetCurrentContext();
516 1812 : ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
517 784 : Local<Promise> promise = promise_resolver->GetPromise();
518 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
519 : return_value.Set(promise);
520 :
521 : std::shared_ptr<i::wasm::CompilationResultResolver> resolver(
522 1568 : new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
523 :
524 784 : bool is_shared = false;
525 784 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
526 784 : if (thrower.error()) {
527 244 : resolver->OnCompilationFailed(thrower.Reify());
528 : return;
529 : }
530 : // Asynchronous compilation handles copying wire bytes if necessary.
531 540 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
532 1080 : i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
533 540 : std::move(resolver), bytes, is_shared);
534 : }
535 :
536 : // WebAssembly.compileStreaming(Promise<Response>) -> Promise
537 24 : void WebAssemblyCompileStreaming(
538 : const v8::FunctionCallbackInfo<v8::Value>& args) {
539 : v8::Isolate* isolate = args.GetIsolate();
540 24 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
541 48 : HandleScope scope(isolate);
542 48 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
543 24 : Local<Context> context = isolate->GetCurrentContext();
544 :
545 : // Create and assign the return value of this function.
546 48 : ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
547 24 : Local<Promise> promise = result_resolver->GetPromise();
548 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
549 : return_value.Set(promise);
550 :
551 : // Prepare the CompilationResultResolver for the compilation.
552 : auto resolver = std::make_shared<AsyncCompilationResolver>(
553 48 : i_isolate, Utils::OpenHandle(*promise));
554 :
555 48 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
556 0 : thrower.CompileError("Wasm code generation disallowed by embedder");
557 0 : resolver->OnCompilationFailed(thrower.Reify());
558 0 : return;
559 : }
560 :
561 : // Allocate the streaming decoder in a Managed so we can pass it to the
562 : // embedder.
563 : i::Handle<i::Managed<WasmStreaming>> data =
564 : i::Managed<WasmStreaming>::Allocate(
565 : i_isolate, 0,
566 48 : base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
567 24 : resolver));
568 :
569 : DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
570 48 : ASSIGN(
571 : v8::Function, compile_callback,
572 : v8::Function::New(context, i_isolate->wasm_streaming_callback(),
573 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
574 :
575 : // The parameter may be of type {Response} or of type {Promise<Response>}.
576 : // Treat either case of parameter as Promise.resolve(parameter)
577 : // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
578 :
579 : // Ending with:
580 : // return Promise.resolve(parameter).then(compile_callback);
581 48 : ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
582 48 : if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
583 :
584 : // We do not have any use of the result here. The {compile_callback} will
585 : // start streaming compilation, which will eventually resolve the promise we
586 : // set as result value.
587 48 : USE(input_resolver->GetPromise()->Then(context, compile_callback));
588 : }
589 :
590 : // WebAssembly.validate(bytes) -> bool
591 128200 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
592 : v8::Isolate* isolate = args.GetIsolate();
593 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
594 256208 : HandleScope scope(isolate);
595 128008 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
596 :
597 128200 : bool is_shared = false;
598 128200 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
599 :
600 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
601 :
602 128200 : if (thrower.error()) {
603 192 : if (thrower.wasm_error()) thrower.Reset(); // Clear error.
604 : return_value.Set(v8::False(isolate));
605 192 : return;
606 : }
607 :
608 128008 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
609 : bool validated = false;
610 128008 : if (is_shared) {
611 : // Make a copy of the wire bytes to avoid concurrent modification.
612 0 : std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
613 : memcpy(copy.get(), bytes.start(), bytes.length());
614 : i::wasm::ModuleWireBytes bytes_copy(copy.get(),
615 0 : copy.get() + bytes.length());
616 : validated = i_isolate->wasm_engine()->SyncValidate(
617 0 : i_isolate, enabled_features, bytes_copy);
618 : } else {
619 : // The wire bytes are not shared, OK to use them directly.
620 : validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
621 128008 : enabled_features, bytes);
622 : }
623 :
624 : return_value.Set(Boolean::New(isolate, validated));
625 : }
626 :
627 : // new WebAssembly.Module(bytes) -> WebAssembly.Module
628 151230 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
629 : v8::Isolate* isolate = args.GetIsolate();
630 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
631 168134 : if (i_isolate->wasm_module_callback()(args)) return;
632 :
633 285557 : HandleScope scope(isolate);
634 134332 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
635 :
636 151222 : if (!args.IsConstructCall()) {
637 32 : thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
638 32 : return;
639 : }
640 302379 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
641 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
642 24 : return;
643 : }
644 :
645 151160 : bool is_shared = false;
646 151160 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
647 :
648 151175 : if (thrower.error()) {
649 : return;
650 : }
651 150909 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
652 : i::MaybeHandle<i::Object> module_obj;
653 150903 : if (is_shared) {
654 : // Make a copy of the wire bytes to avoid concurrent modification.
655 0 : std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
656 : memcpy(copy.get(), bytes.start(), bytes.length());
657 : i::wasm::ModuleWireBytes bytes_copy(copy.get(),
658 0 : copy.get() + bytes.length());
659 : module_obj = i_isolate->wasm_engine()->SyncCompile(
660 0 : i_isolate, enabled_features, &thrower, bytes_copy);
661 : } else {
662 : // The wire bytes are not shared, OK to use them directly.
663 : module_obj = i_isolate->wasm_engine()->SyncCompile(
664 150903 : i_isolate, enabled_features, &thrower, bytes);
665 : }
666 :
667 150905 : if (module_obj.is_null()) return;
668 :
669 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
670 : return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
671 : }
672 :
673 : // WebAssembly.Module.imports(module) -> Array<Import>
674 248 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
675 392 : HandleScope scope(args.GetIsolate());
676 : v8::Isolate* isolate = args.GetIsolate();
677 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
678 144 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
679 :
680 248 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
681 352 : if (thrower.error()) return;
682 144 : auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
683 : args.GetReturnValue().Set(Utils::ToLocal(imports));
684 : }
685 :
686 : // WebAssembly.Module.exports(module) -> Array<Export>
687 240 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
688 376 : HandleScope scope(args.GetIsolate());
689 : v8::Isolate* isolate = args.GetIsolate();
690 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
691 136 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
692 :
693 240 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
694 344 : if (thrower.error()) return;
695 136 : auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
696 : args.GetReturnValue().Set(Utils::ToLocal(exports));
697 : }
698 :
699 : // WebAssembly.Module.customSections(module, name) -> Array<Section>
700 376 : void WebAssemblyModuleCustomSections(
701 : const v8::FunctionCallbackInfo<v8::Value>& args) {
702 624 : HandleScope scope(args.GetIsolate());
703 : v8::Isolate* isolate = args.GetIsolate();
704 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
705 : ScheduledErrorThrower thrower(i_isolate,
706 248 : "WebAssembly.Module.customSections()");
707 :
708 376 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
709 504 : if (thrower.error()) return;
710 :
711 264 : if (args[1]->IsUndefined()) {
712 8 : thrower.TypeError("Argument 1 is required");
713 8 : return;
714 : }
715 :
716 : i::MaybeHandle<i::Object> maybe_name =
717 256 : i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
718 : i::Handle<i::Object> name;
719 256 : if (!maybe_name.ToHandle(&name)) return;
720 : auto custom_sections =
721 : i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
722 248 : i::Handle<i::String>::cast(name), &thrower);
723 248 : if (thrower.error()) return;
724 : args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
725 : }
726 :
727 129106 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
728 : Local<Value> module,
729 : Local<Value> ffi) {
730 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
731 :
732 : i::MaybeHandle<i::Object> instance_object;
733 : {
734 129028 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
735 :
736 : // TODO(ahaas): These checks on the module should not be necessary here They
737 : // are just a workaround for https://crbug.com/837417.
738 : i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
739 129106 : if (!module_obj->IsWasmModuleObject()) {
740 0 : thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
741 0 : return {};
742 : }
743 :
744 : i::MaybeHandle<i::JSReceiver> maybe_imports =
745 129106 : GetValueAsImports(ffi, &thrower);
746 129108 : if (thrower.error()) return {};
747 :
748 : instance_object = i_isolate->wasm_engine()->SyncInstantiate(
749 : i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
750 129028 : maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
751 : }
752 :
753 : DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
754 129028 : if (instance_object.is_null()) return {};
755 127380 : return Utils::ToLocal(instance_object.ToHandleChecked());
756 : }
757 :
758 : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
759 129280 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
760 : Isolate* isolate = args.GetIsolate();
761 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
762 : i_isolate->CountUsage(
763 129280 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
764 :
765 258390 : HandleScope scope(args.GetIsolate());
766 129453 : if (i_isolate->wasm_instance_callback()(args)) return;
767 :
768 129108 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
769 129275 : if (!args.IsConstructCall()) {
770 24 : thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
771 24 : return;
772 : }
773 :
774 129251 : GetFirstArgumentAsModule(args, &thrower);
775 129249 : if (thrower.error()) return;
776 :
777 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
778 : // We'll check for that in WebAssemblyInstantiateImpl.
779 129108 : Local<Value> data = args[1];
780 :
781 : Local<Value> instance;
782 258216 : if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
783 : args.GetReturnValue().Set(instance);
784 : }
785 : }
786 :
787 0 : void WebAssemblyInstantiateStreaming(
788 : const v8::FunctionCallbackInfo<v8::Value>& args) {
789 0 : v8::Isolate* isolate = args.GetIsolate();
790 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
791 : i_isolate->CountUsage(
792 0 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
793 :
794 0 : HandleScope scope(isolate);
795 0 : Local<Context> context = isolate->GetCurrentContext();
796 : ScheduledErrorThrower thrower(i_isolate,
797 0 : "WebAssembly.instantiateStreaming()");
798 :
799 : // Create and assign the return value of this function.
800 0 : ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
801 0 : Local<Promise> promise = result_resolver->GetPromise();
802 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
803 : return_value.Set(promise);
804 :
805 : // Create an InstantiateResultResolver in case there is an issue with the
806 : // passed parameters.
807 : std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
808 : new InstantiateModuleResultResolver(i_isolate,
809 0 : Utils::OpenHandle(*promise)));
810 :
811 0 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
812 0 : thrower.CompileError("Wasm code generation disallowed by embedder");
813 0 : resolver->OnInstantiationFailed(thrower.Reify());
814 0 : return;
815 : }
816 :
817 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
818 0 : Local<Value> ffi = args[1];
819 : i::MaybeHandle<i::JSReceiver> maybe_imports =
820 0 : GetValueAsImports(ffi, &thrower);
821 :
822 0 : if (thrower.error()) {
823 0 : resolver->OnInstantiationFailed(thrower.Reify());
824 0 : return;
825 : }
826 :
827 : // We start compilation now, we have no use for the
828 : // {InstantiationResultResolver}.
829 : resolver.reset();
830 :
831 : std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
832 : new AsyncInstantiateCompileResultResolver(
833 0 : i_isolate, Utils::OpenHandle(*promise), maybe_imports));
834 :
835 : // Allocate the streaming decoder in a Managed so we can pass it to the
836 : // embedder.
837 : i::Handle<i::Managed<WasmStreaming>> data =
838 : i::Managed<WasmStreaming>::Allocate(
839 : i_isolate, 0,
840 0 : base::make_unique<WasmStreaming::WasmStreamingImpl>(
841 0 : isolate, compilation_resolver));
842 :
843 : DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
844 0 : ASSIGN(
845 : v8::Function, compile_callback,
846 : v8::Function::New(context, i_isolate->wasm_streaming_callback(),
847 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
848 :
849 : // The parameter may be of type {Response} or of type {Promise<Response>}.
850 : // Treat either case of parameter as Promise.resolve(parameter)
851 : // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
852 :
853 : // Ending with:
854 : // return Promise.resolve(parameter).then(compile_callback);
855 0 : ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
856 0 : if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
857 :
858 : // We do not have any use of the result here. The {compile_callback} will
859 : // start streaming compilation, which will eventually resolve the promise we
860 : // set as result value.
861 0 : USE(input_resolver->GetPromise()->Then(context, compile_callback));
862 : }
863 :
864 : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
865 : // WebAssembly.instantiate(bytes, imports) ->
866 : // {module: WebAssembly.Module, instance: WebAssembly.Instance}
867 7319 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
868 : v8::Isolate* isolate = args.GetIsolate();
869 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
870 : i_isolate->CountUsage(
871 7319 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
872 :
873 1812 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
874 :
875 9131 : HandleScope scope(isolate);
876 :
877 7319 : Local<Context> context = isolate->GetCurrentContext();
878 :
879 20145 : ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
880 7319 : Local<Promise> promise = promise_resolver->GetPromise();
881 : args.GetReturnValue().Set(promise);
882 :
883 : std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
884 : new InstantiateModuleResultResolver(i_isolate,
885 7319 : Utils::OpenHandle(*promise)));
886 :
887 : Local<Value> first_arg_value = args[0];
888 : i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
889 7319 : if (!first_arg->IsJSObject()) {
890 : thrower.TypeError(
891 4643 : "Argument 0 must be a buffer source or a WebAssembly.Module object");
892 4643 : resolver->OnInstantiationFailed(thrower.Reify());
893 4643 : return;
894 : }
895 :
896 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
897 2676 : Local<Value> ffi = args[1];
898 : i::MaybeHandle<i::JSReceiver> maybe_imports =
899 2676 : GetValueAsImports(ffi, &thrower);
900 :
901 2676 : if (thrower.error()) {
902 160 : resolver->OnInstantiationFailed(thrower.Reify());
903 160 : return;
904 : }
905 :
906 2516 : if (first_arg->IsWasmModuleObject()) {
907 : i::Handle<i::WasmModuleObject> module_obj =
908 576 : i::Handle<i::WasmModuleObject>::cast(first_arg);
909 :
910 576 : i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
911 576 : module_obj, maybe_imports);
912 : return;
913 : }
914 :
915 1940 : bool is_shared = false;
916 1940 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
917 1940 : if (thrower.error()) {
918 104 : resolver->OnInstantiationFailed(thrower.Reify());
919 104 : return;
920 : }
921 :
922 : // We start compilation now, we have no use for the
923 : // {InstantiationResultResolver}.
924 : resolver.reset();
925 :
926 : std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
927 : new AsyncInstantiateCompileResultResolver(
928 3672 : i_isolate, Utils::OpenHandle(*promise), maybe_imports));
929 :
930 : // The first parameter is a buffer source, we have to check if we are allowed
931 : // to compile it.
932 3672 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
933 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
934 24 : compilation_resolver->OnCompilationFailed(thrower.Reify());
935 : return;
936 : }
937 :
938 : // Asynchronous compilation handles copying wire bytes if necessary.
939 1812 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
940 3624 : i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
941 : std::move(compilation_resolver), bytes,
942 1812 : is_shared);
943 : }
944 :
945 8808 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
946 : Local<Context> context, v8::Local<v8::Value> value,
947 : i::Handle<i::String> property_name, int64_t* result,
948 : int64_t lower_bound, uint64_t upper_bound) {
949 : uint32_t number;
950 8808 : if (!EnforceUint32(property_name, value, context, thrower, &number)) {
951 : return false;
952 : }
953 8496 : if (number < lower_bound) {
954 : thrower->RangeError("Property '%s': value %" PRIu32
955 : " is below the lower bound %" PRIx64,
956 144 : property_name->ToCString().get(), number, lower_bound);
957 : return false;
958 : }
959 8448 : if (number > upper_bound) {
960 : thrower->RangeError("Property '%s': value %" PRIu32
961 : " is above the upper bound %" PRIu64,
962 192 : property_name->ToCString().get(), number, upper_bound);
963 : return false;
964 : }
965 :
966 8384 : *result = static_cast<int64_t>(number);
967 : return true;
968 : }
969 :
970 12830 : bool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
971 : Local<Context> context,
972 : Local<v8::Object> object,
973 : Local<String> property, bool* has_property,
974 : int64_t* result, int64_t lower_bound,
975 : uint64_t upper_bound) {
976 : v8::Local<v8::Value> value;
977 25660 : if (!object->Get(context, property).ToLocal(&value)) {
978 : return false;
979 : }
980 :
981 : // Web IDL: dictionary presence
982 : // https://heycam.github.io/webidl/#dfn-present
983 12830 : if (value->IsUndefined()) {
984 4022 : if (has_property != nullptr) *has_property = false;
985 : return true;
986 : }
987 :
988 8808 : if (has_property != nullptr) *has_property = true;
989 8808 : i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property);
990 :
991 : return GetIntegerProperty(isolate, thrower, context, value, property_name,
992 8808 : result, lower_bound, upper_bound);
993 : }
994 :
995 : // Fetch 'initial' or 'minimum' property from object. If both are provided,
996 : // 'initial' is used.
997 : // TODO(aseemgarg): change behavior when the following bug is resolved:
998 : // https://github.com/WebAssembly/js-types/issues/6
999 6519 : bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
1000 : Local<Context> context,
1001 : Local<v8::Object> object, int64_t* result,
1002 : int64_t lower_bound, uint64_t upper_bound) {
1003 6519 : bool has_initial = false;
1004 6519 : if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
1005 : v8_str(isolate, "initial"), &has_initial,
1006 : result, lower_bound, upper_bound)) {
1007 : return false;
1008 : }
1009 6311 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1010 6311 : if (!has_initial && enabled_features.type_reflection) {
1011 32 : if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
1012 : v8_str(isolate, "minimum"), &has_initial,
1013 : result, lower_bound, upper_bound)) {
1014 : return false;
1015 : }
1016 : }
1017 6311 : if (!has_initial) {
1018 : // TODO(aseemgarg): update error message when the spec issue is resolved.
1019 32 : thrower->TypeError("Property 'initial' is required");
1020 32 : return false;
1021 : }
1022 : return true;
1023 : }
1024 :
1025 : // new WebAssembly.Table(args) -> WebAssembly.Table
1026 2152 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
1027 : v8::Isolate* isolate = args.GetIsolate();
1028 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1029 3848 : HandleScope scope(isolate);
1030 1696 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
1031 2152 : if (!args.IsConstructCall()) {
1032 24 : thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
1033 24 : return;
1034 : }
1035 2128 : if (!args[0]->IsObject()) {
1036 120 : thrower.TypeError("Argument 0 must be a table descriptor");
1037 120 : return;
1038 : }
1039 2008 : Local<Context> context = isolate->GetCurrentContext();
1040 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1041 : i::wasm::ValueType type;
1042 : // The descriptor's 'element'.
1043 : {
1044 : v8::MaybeLocal<v8::Value> maybe =
1045 2008 : descriptor->Get(context, v8_str(isolate, "element"));
1046 : v8::Local<v8::Value> value;
1047 2096 : if (!maybe.ToLocal(&value)) return;
1048 : v8::Local<v8::String> string;
1049 4016 : if (!value->ToString(context).ToLocal(&string)) return;
1050 2008 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1051 2008 : if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
1052 : type = i::wasm::kWasmAnyFunc;
1053 136 : } else if (enabled_features.anyref &&
1054 24 : string->StringEquals(v8_str(isolate, "anyref"))) {
1055 : type = i::wasm::kWasmAnyRef;
1056 : } else {
1057 88 : thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
1058 88 : return;
1059 : }
1060 : }
1061 :
1062 1920 : int64_t initial = 0;
1063 1920 : if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
1064 : &initial, 0,
1065 1920 : i::wasm::max_table_init_entries())) {
1066 : return;
1067 : }
1068 : // The descriptor's 'maximum'.
1069 1816 : int64_t maximum = -1;
1070 1816 : bool has_maximum = true;
1071 3632 : if (!GetOptionalIntegerProperty(
1072 : isolate, &thrower, context, descriptor, v8_str(isolate, "maximum"),
1073 1816 : &has_maximum, &maximum, initial, i::wasm::max_table_init_entries())) {
1074 : return;
1075 : }
1076 :
1077 : i::Handle<i::FixedArray> fixed_array;
1078 : i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
1079 : i_isolate, type, static_cast<uint32_t>(initial), has_maximum,
1080 1696 : static_cast<uint32_t>(maximum), &fixed_array);
1081 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1082 : return_value.Set(Utils::ToLocal(table_obj));
1083 : }
1084 :
1085 4743 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
1086 : v8::Isolate* isolate = args.GetIsolate();
1087 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1088 9094 : HandleScope scope(isolate);
1089 4351 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
1090 4743 : if (!args.IsConstructCall()) {
1091 24 : thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
1092 24 : return;
1093 : }
1094 4719 : if (!args[0]->IsObject()) {
1095 120 : thrower.TypeError("Argument 0 must be a memory descriptor");
1096 120 : return;
1097 : }
1098 4599 : Local<Context> context = isolate->GetCurrentContext();
1099 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1100 :
1101 4599 : int64_t initial = 0;
1102 4599 : if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
1103 4599 : &initial, 0, i::wasm::max_mem_pages())) {
1104 : return;
1105 : }
1106 : // The descriptor's 'maximum'.
1107 4463 : int64_t maximum = -1;
1108 8926 : if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
1109 : v8_str(isolate, "maximum"), nullptr, &maximum,
1110 : initial, i::wasm::kSpecMaxWasmMemoryPages)) {
1111 : return;
1112 : }
1113 :
1114 : bool is_shared_memory = false;
1115 4367 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1116 4367 : if (enabled_features.threads) {
1117 : // Shared property of descriptor
1118 : Local<String> shared_key = v8_str(isolate, "shared");
1119 : v8::MaybeLocal<v8::Value> maybe_value =
1120 297 : descriptor->Get(context, shared_key);
1121 : v8::Local<v8::Value> value;
1122 297 : if (maybe_value.ToLocal(&value)) {
1123 297 : is_shared_memory = value->BooleanValue(isolate);
1124 : }
1125 : // Throw TypeError if shared is true, and the descriptor has no "maximum"
1126 297 : if (is_shared_memory && maximum == -1) {
1127 : thrower.TypeError(
1128 8 : "If shared is true, maximum property should be defined.");
1129 : return;
1130 : }
1131 : }
1132 :
1133 : i::Handle<i::JSObject> memory_obj;
1134 8718 : if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
1135 : static_cast<uint32_t>(maximum),
1136 4359 : is_shared_memory)
1137 : .ToHandle(&memory_obj)) {
1138 8 : thrower.RangeError("could not allocate memory");
1139 8 : return;
1140 : }
1141 4351 : if (is_shared_memory) {
1142 : i::Handle<i::JSArrayBuffer> buffer(
1143 : i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(),
1144 : i_isolate);
1145 : Maybe<bool> result =
1146 249 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1147 249 : if (!result.FromJust()) {
1148 : thrower.TypeError(
1149 0 : "Status of setting SetIntegrityLevel of buffer is false.");
1150 : return;
1151 : }
1152 : }
1153 : args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
1154 : }
1155 :
1156 7392 : void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
1157 : v8::Isolate* isolate = args.GetIsolate();
1158 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1159 14528 : HandleScope scope(isolate);
1160 7136 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
1161 7392 : if (!args.IsConstructCall()) {
1162 8 : thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
1163 8 : return;
1164 : }
1165 7384 : if (!args[0]->IsObject()) {
1166 104 : thrower.TypeError("Argument 0 must be a global descriptor");
1167 104 : return;
1168 : }
1169 7280 : Local<Context> context = isolate->GetCurrentContext();
1170 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1171 :
1172 : // The descriptor's 'mutable'.
1173 : bool is_mutable = false;
1174 : {
1175 : Local<String> mutable_key = v8_str(isolate, "mutable");
1176 7280 : v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
1177 : v8::Local<v8::Value> value;
1178 7280 : if (maybe.ToLocal(&value)) {
1179 7280 : is_mutable = value->BooleanValue(isolate);
1180 : }
1181 : }
1182 :
1183 : // The descriptor's type, called 'value'. It is called 'value' because this
1184 : // descriptor is planned to be re-used as the global's type for reflection,
1185 : // so calling it 'type' is redundant.
1186 : i::wasm::ValueType type;
1187 : {
1188 : v8::MaybeLocal<v8::Value> maybe =
1189 7280 : descriptor->Get(context, v8_str(isolate, "value"));
1190 : v8::Local<v8::Value> value;
1191 7400 : if (!maybe.ToLocal(&value)) return;
1192 : v8::Local<v8::String> string;
1193 14560 : if (!value->ToString(context).ToLocal(&string)) return;
1194 :
1195 7280 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1196 7280 : if (string->StringEquals(v8_str(isolate, "i32"))) {
1197 : type = i::wasm::kWasmI32;
1198 4696 : } else if (string->StringEquals(v8_str(isolate, "f32"))) {
1199 : type = i::wasm::kWasmF32;
1200 1760 : } else if (string->StringEquals(v8_str(isolate, "i64"))) {
1201 : type = i::wasm::kWasmI64;
1202 1664 : } else if (string->StringEquals(v8_str(isolate, "f64"))) {
1203 : type = i::wasm::kWasmF64;
1204 488 : } else if (enabled_features.anyref &&
1205 184 : string->StringEquals(v8_str(isolate, "anyref"))) {
1206 : type = i::wasm::kWasmAnyRef;
1207 232 : } else if (enabled_features.anyref &&
1208 56 : string->StringEquals(v8_str(isolate, "anyfunc"))) {
1209 : type = i::wasm::kWasmAnyFunc;
1210 : } else {
1211 : thrower.TypeError(
1212 : "Descriptor property 'value' must be 'i32', 'i64', 'f32', or "
1213 120 : "'f64'");
1214 120 : return;
1215 : }
1216 : }
1217 :
1218 : const uint32_t offset = 0;
1219 : i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
1220 : i::WasmGlobalObject::New(i_isolate, i::MaybeHandle<i::JSArrayBuffer>(),
1221 : i::MaybeHandle<i::FixedArray>(), type, offset,
1222 7160 : is_mutable);
1223 :
1224 : i::Handle<i::WasmGlobalObject> global_obj;
1225 7160 : if (!maybe_global_obj.ToHandle(&global_obj)) {
1226 0 : thrower.RangeError("could not allocate memory");
1227 0 : return;
1228 : }
1229 :
1230 : // Convert value to a WebAssembly value, the default value is 0.
1231 : Local<v8::Value> value = Local<Value>::Cast(args[1]);
1232 7160 : switch (type) {
1233 : case i::wasm::kWasmI32: {
1234 : int32_t i32_value = 0;
1235 2584 : if (!value->IsUndefined()) {
1236 : v8::Local<v8::Int32> int32_value;
1237 4832 : if (!value->ToInt32(context).ToLocal(&int32_value)) return;
1238 4832 : if (!int32_value->Int32Value(context).To(&i32_value)) return;
1239 : }
1240 2584 : global_obj->SetI32(i32_value);
1241 : break;
1242 : }
1243 : case i::wasm::kWasmI64: {
1244 : int64_t i64_value = 0;
1245 96 : if (!value->IsUndefined()) {
1246 48 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1247 48 : if (!enabled_features.bigint) {
1248 16 : thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
1249 16 : return;
1250 : }
1251 :
1252 : v8::Local<v8::BigInt> bigint_value;
1253 64 : if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
1254 24 : i64_value = bigint_value->Int64Value();
1255 : }
1256 72 : global_obj->SetI64(i64_value);
1257 72 : break;
1258 : }
1259 : case i::wasm::kWasmF32: {
1260 : float f32_value = 0;
1261 2936 : if (!value->IsUndefined()) {
1262 : double f64_value = 0;
1263 : v8::Local<v8::Number> number_value;
1264 5600 : if (!value->ToNumber(context).ToLocal(&number_value)) return;
1265 5600 : if (!number_value->NumberValue(context).To(&f64_value)) return;
1266 2800 : f32_value = static_cast<float>(f64_value);
1267 : }
1268 2936 : global_obj->SetF32(f32_value);
1269 2936 : break;
1270 : }
1271 : case i::wasm::kWasmF64: {
1272 : double f64_value = 0;
1273 1360 : if (!value->IsUndefined()) {
1274 : v8::Local<v8::Number> number_value;
1275 2448 : if (!value->ToNumber(context).ToLocal(&number_value)) return;
1276 2448 : if (!number_value->NumberValue(context).To(&f64_value)) return;
1277 : }
1278 1360 : global_obj->SetF64(f64_value);
1279 : break;
1280 : }
1281 : case i::wasm::kWasmAnyRef: {
1282 128 : if (args.Length() < 2) {
1283 : // When no inital value is provided, we have to use the WebAssembly
1284 : // default value 'null', and not the JS default value 'undefined'.
1285 32 : global_obj->SetAnyRef(i_isolate->factory()->null_value());
1286 32 : break;
1287 : }
1288 96 : global_obj->SetAnyRef(Utils::OpenHandle(*value));
1289 96 : break;
1290 : }
1291 : case i::wasm::kWasmAnyFunc: {
1292 56 : if (args.Length() < 2) {
1293 : // When no inital value is provided, we have to use the WebAssembly
1294 : // default value 'null', and not the JS default value 'undefined'.
1295 16 : global_obj->SetAnyFunc(i_isolate, i_isolate->factory()->null_value());
1296 16 : break;
1297 : }
1298 :
1299 40 : if (!global_obj->SetAnyFunc(i_isolate, Utils::OpenHandle(*value))) {
1300 : thrower.TypeError(
1301 : "The value of anyfunc globals must be null or an "
1302 8 : "exported function");
1303 : }
1304 : break;
1305 : }
1306 : default:
1307 0 : UNREACHABLE();
1308 : }
1309 :
1310 : i::Handle<i::JSObject> global_js_object(global_obj);
1311 : args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
1312 : }
1313 :
1314 : // WebAssembly.Exception
1315 8 : void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
1316 : v8::Isolate* isolate = args.GetIsolate();
1317 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1318 16 : HandleScope scope(isolate);
1319 8 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
1320 8 : thrower.TypeError("WebAssembly.Exception cannot be called");
1321 8 : }
1322 :
1323 : constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
1324 : constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
1325 : constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
1326 : constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
1327 :
1328 : #define EXTRACT_THIS(var, WasmType) \
1329 : i::Handle<i::WasmType> var; \
1330 : { \
1331 : i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
1332 : if (!this_arg->Is##WasmType()) { \
1333 : thrower.TypeError("Receiver is not a %s", kName_##WasmType); \
1334 : return; \
1335 : } \
1336 : var = i::Handle<i::WasmType>::cast(this_arg); \
1337 : }
1338 :
1339 42519285 : void WebAssemblyInstanceGetExports(
1340 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1341 : v8::Isolate* isolate = args.GetIsolate();
1342 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1343 85038483 : HandleScope scope(isolate);
1344 42519197 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
1345 42519283 : EXTRACT_THIS(receiver, WasmInstanceObject);
1346 : i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
1347 : args.GetReturnValue().Set(Utils::ToLocal(exports_object));
1348 : }
1349 :
1350 8000 : void WebAssemblyTableGetLength(
1351 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1352 : v8::Isolate* isolate = args.GetIsolate();
1353 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1354 15888 : HandleScope scope(isolate);
1355 7888 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
1356 8000 : EXTRACT_THIS(receiver, WasmTableObject);
1357 7888 : args.GetReturnValue().Set(
1358 15776 : v8::Number::New(isolate, receiver->current_length()));
1359 : }
1360 :
1361 : // WebAssembly.Table.grow(num) -> num
1362 744 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1363 : v8::Isolate* isolate = args.GetIsolate();
1364 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1365 1176 : HandleScope scope(isolate);
1366 432 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
1367 744 : Local<Context> context = isolate->GetCurrentContext();
1368 744 : EXTRACT_THIS(receiver, WasmTableObject);
1369 :
1370 : uint32_t grow_by;
1371 648 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) {
1372 : return;
1373 : }
1374 :
1375 : i::Handle<i::FixedArray> old_array(receiver->elements(), i_isolate);
1376 496 : uint32_t old_size = static_cast<uint32_t>(old_array->length());
1377 :
1378 : uint64_t max_size64 = receiver->maximum_length().IsUndefined(i_isolate)
1379 : ? i::FLAG_wasm_max_table_size
1380 936 : : receiver->maximum_length()->Number();
1381 496 : if (max_size64 > i::FLAG_wasm_max_table_size) {
1382 : max_size64 = i::FLAG_wasm_max_table_size;
1383 : }
1384 :
1385 : DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
1386 :
1387 : uint64_t new_size64 =
1388 496 : static_cast<uint64_t>(old_size) + static_cast<uint64_t>(grow_by);
1389 496 : if (new_size64 > max_size64) {
1390 64 : thrower.RangeError("maximum table size exceeded");
1391 64 : return;
1392 : }
1393 : uint32_t new_size = static_cast<uint32_t>(new_size64);
1394 :
1395 432 : if (new_size != old_size) {
1396 400 : receiver->Grow(i_isolate, new_size - old_size);
1397 :
1398 : i::Handle<i::FixedArray> new_array =
1399 400 : i_isolate->factory()->NewFixedArray(new_size);
1400 9597312 : for (uint32_t i = 0; i < old_size; ++i) {
1401 9596912 : new_array->set(i, old_array->get(i));
1402 : }
1403 400 : i::Object null = i::ReadOnlyRoots(i_isolate).null_value();
1404 170590448 : for (uint32_t i = old_size; i < new_size; ++i) new_array->set(i, null);
1405 400 : receiver->set_elements(*new_array);
1406 : }
1407 :
1408 : // TODO(gdeepti): use weak links for instances
1409 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1410 : return_value.Set(old_size);
1411 : }
1412 :
1413 : // WebAssembly.Table.get(num) -> JSFunction
1414 11080 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1415 : v8::Isolate* isolate = args.GetIsolate();
1416 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1417 21144 : HandleScope scope(isolate);
1418 10064 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
1419 11080 : Local<Context> context = isolate->GetCurrentContext();
1420 11080 : EXTRACT_THIS(receiver, WasmTableObject);
1421 :
1422 : uint32_t index;
1423 10984 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
1424 : return;
1425 : }
1426 10512 : if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) {
1427 448 : thrower.RangeError("invalid index %u into function table", index);
1428 448 : return;
1429 : }
1430 :
1431 : i::Handle<i::Object> result =
1432 10064 : i::WasmTableObject::Get(i_isolate, receiver, index);
1433 :
1434 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1435 : return_value.Set(Utils::ToLocal(result));
1436 : }
1437 :
1438 : // WebAssembly.Table.set(num, JSFunction)
1439 4000 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1440 : v8::Isolate* isolate = args.GetIsolate();
1441 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1442 7088 : HandleScope scope(isolate);
1443 3088 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
1444 4000 : Local<Context> context = isolate->GetCurrentContext();
1445 4000 : EXTRACT_THIS(table_object, WasmTableObject);
1446 :
1447 : // Parameter 0.
1448 : uint32_t index;
1449 3896 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
1450 : return;
1451 : }
1452 3664 : if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) {
1453 328 : thrower.RangeError("invalid index %u into function table", index);
1454 328 : return;
1455 : }
1456 :
1457 3336 : i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
1458 3336 : if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) {
1459 248 : thrower.TypeError("Argument 1 must be null or a WebAssembly function");
1460 248 : return;
1461 : }
1462 3088 : i::WasmTableObject::Set(i_isolate, table_object, index, element);
1463 : }
1464 :
1465 : // WebAssembly.Table.type(WebAssembly.Table) -> TableType
1466 96 : void WebAssemblyTableGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1467 : v8::Isolate* isolate = args.GetIsolate();
1468 160 : HandleScope scope(isolate);
1469 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1470 64 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()");
1471 :
1472 96 : auto maybe_table = GetFirstArgumentAsTable(args, &thrower);
1473 128 : if (thrower.error()) return;
1474 : i::Handle<i::WasmTableObject> table = maybe_table.ToHandleChecked();
1475 64 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1476 :
1477 : Local<String> element;
1478 64 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1479 64 : if (table->type() == i::wasm::ValueType::kWasmAnyFunc) {
1480 : element = v8_str(isolate, "anyfunc");
1481 16 : } else if (enabled_features.anyref &&
1482 : table->type() == i::wasm::ValueType::kWasmAnyRef) {
1483 : element = v8_str(isolate, "anyref");
1484 : } else {
1485 0 : UNREACHABLE();
1486 : }
1487 : // TODO(aseemgarg): update anyfunc to funcref
1488 192 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1489 128 : v8_str(isolate, "element"), element)
1490 : .IsJust()) {
1491 : return;
1492 : }
1493 :
1494 64 : uint32_t curr_size = table->current_length();
1495 : DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
1496 192 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1497 : v8_str(isolate, "minimum"),
1498 : v8::Integer::NewFromUnsigned(
1499 192 : isolate, static_cast<uint32_t>(curr_size)))
1500 : .IsJust()) {
1501 : return;
1502 : }
1503 :
1504 64 : if (!table->maximum_length()->IsUndefined()) {
1505 32 : uint64_t max_size = table->maximum_length()->Number();
1506 : DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
1507 96 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1508 : v8_str(isolate, "maximum"),
1509 : v8::Integer::NewFromUnsigned(
1510 96 : isolate, static_cast<uint32_t>(max_size)))
1511 : .IsJust()) {
1512 : return;
1513 : }
1514 : }
1515 :
1516 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1517 : return_value.Set(ret);
1518 : }
1519 :
1520 : // WebAssembly.Memory.grow(num) -> num
1521 724 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1522 : v8::Isolate* isolate = args.GetIsolate();
1523 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1524 1160 : HandleScope scope(isolate);
1525 436 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
1526 724 : Local<Context> context = isolate->GetCurrentContext();
1527 724 : EXTRACT_THIS(receiver, WasmMemoryObject);
1528 :
1529 : uint32_t delta_size;
1530 636 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_size)) {
1531 : return;
1532 : }
1533 :
1534 516 : uint64_t max_size64 = receiver->maximum_pages();
1535 516 : if (max_size64 > uint64_t{i::wasm::max_mem_pages()}) {
1536 168 : max_size64 = i::wasm::max_mem_pages();
1537 : }
1538 : i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);
1539 516 : if (!old_buffer->is_growable()) {
1540 8 : thrower.RangeError("This memory cannot be grown");
1541 8 : return;
1542 : }
1543 :
1544 : DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
1545 :
1546 508 : uint64_t old_size64 = old_buffer->byte_length() / i::wasm::kWasmPageSize;
1547 508 : uint64_t new_size64 = old_size64 + static_cast<uint64_t>(delta_size);
1548 :
1549 508 : if (new_size64 > max_size64) {
1550 72 : thrower.RangeError("Maximum memory size exceeded");
1551 72 : return;
1552 : }
1553 :
1554 436 : int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_size);
1555 436 : if (ret == -1) {
1556 0 : thrower.RangeError("Unable to grow instance memory.");
1557 0 : return;
1558 : }
1559 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1560 : return_value.Set(ret);
1561 : }
1562 :
1563 : // WebAssembly.Memory.buffer -> ArrayBuffer
1564 10753109 : void WebAssemblyMemoryGetBuffer(
1565 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1566 : v8::Isolate* isolate = args.GetIsolate();
1567 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1568 21506106 : HandleScope scope(isolate);
1569 10752997 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
1570 10753109 : EXTRACT_THIS(receiver, WasmMemoryObject);
1571 :
1572 : i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
1573 : DCHECK(buffer_obj->IsJSArrayBuffer());
1574 : i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
1575 : i_isolate);
1576 10752997 : if (buffer->is_shared()) {
1577 : // TODO(gdeepti): More needed here for when cached buffer, and current
1578 : // buffer are out of sync, handle that here when bounds checks, and Grow
1579 : // are handled correctly.
1580 : Maybe<bool> result =
1581 10750749 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1582 10750749 : if (!result.FromJust()) {
1583 : thrower.TypeError(
1584 0 : "Status of setting SetIntegrityLevel of buffer is false.");
1585 : }
1586 : }
1587 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1588 : return_value.Set(Utils::ToLocal(buffer));
1589 : }
1590 :
1591 : // WebAssembly.Memory.type(WebAssembly.Memory) -> MemoryType
1592 80 : void WebAssemblyMemoryGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1593 : v8::Isolate* isolate = args.GetIsolate();
1594 128 : HandleScope scope(isolate);
1595 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1596 48 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()");
1597 :
1598 80 : auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
1599 112 : if (thrower.error()) return;
1600 : i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
1601 48 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1602 : i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
1603 :
1604 48 : size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
1605 : DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
1606 144 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1607 : v8_str(isolate, "minimum"),
1608 : v8::Integer::NewFromUnsigned(
1609 144 : isolate, static_cast<uint32_t>(curr_size)))
1610 : .IsJust()) {
1611 : return;
1612 : }
1613 :
1614 48 : if (memory->has_maximum_pages()) {
1615 24 : uint64_t max_size = memory->maximum_pages();
1616 : DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
1617 72 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1618 : v8_str(isolate, "maximum"),
1619 : v8::Integer::NewFromUnsigned(
1620 72 : isolate, static_cast<uint32_t>(max_size)))
1621 : .IsJust()) {
1622 : return;
1623 : }
1624 : }
1625 :
1626 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1627 : return_value.Set(ret);
1628 : }
1629 :
1630 9224 : void WebAssemblyGlobalGetValueCommon(
1631 : const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
1632 : v8::Isolate* isolate = args.GetIsolate();
1633 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1634 18288 : HandleScope scope(isolate);
1635 9064 : ScheduledErrorThrower thrower(i_isolate, name);
1636 9224 : EXTRACT_THIS(receiver, WasmGlobalObject);
1637 :
1638 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1639 :
1640 9064 : switch (receiver->type()) {
1641 : case i::wasm::kWasmI32:
1642 6992 : return_value.Set(receiver->GetI32());
1643 : break;
1644 : case i::wasm::kWasmI64: {
1645 112 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1646 112 : if (enabled_features.bigint) {
1647 144 : Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
1648 :
1649 : return_value.Set(value);
1650 : } else {
1651 40 : thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
1652 : }
1653 : break;
1654 : }
1655 : case i::wasm::kWasmF32:
1656 9864 : return_value.Set(receiver->GetF32());
1657 : break;
1658 : case i::wasm::kWasmF64:
1659 3504 : return_value.Set(receiver->GetF64());
1660 : break;
1661 : case i::wasm::kWasmAnyRef:
1662 : case i::wasm::kWasmAnyFunc:
1663 : case i::wasm::kWasmExceptRef:
1664 832 : return_value.Set(Utils::ToLocal(receiver->GetRef()));
1665 : break;
1666 : default:
1667 0 : UNREACHABLE();
1668 : }
1669 : }
1670 :
1671 : // WebAssembly.Global.valueOf() -> num
1672 3224 : void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
1673 3224 : return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
1674 : }
1675 :
1676 : // get WebAssembly.Global.value -> num
1677 6000 : void WebAssemblyGlobalGetValue(
1678 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1679 6000 : return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
1680 : }
1681 :
1682 : // set WebAssembly.Global.value(num)
1683 2840 : void WebAssemblyGlobalSetValue(
1684 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1685 : v8::Isolate* isolate = args.GetIsolate();
1686 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1687 5368 : HandleScope scope(isolate);
1688 2840 : Local<Context> context = isolate->GetCurrentContext();
1689 2528 : ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
1690 2840 : EXTRACT_THIS(receiver, WasmGlobalObject);
1691 :
1692 2768 : if (!receiver->is_mutable()) {
1693 216 : thrower.TypeError("Can't set the value of an immutable global.");
1694 216 : return;
1695 : }
1696 2552 : if (args[0]->IsUndefined()) {
1697 16 : thrower.TypeError("Argument 0 is required");
1698 16 : return;
1699 : }
1700 :
1701 2536 : switch (receiver->type()) {
1702 : case i::wasm::kWasmI32: {
1703 : int32_t i32_value = 0;
1704 2000 : if (!args[0]->Int32Value(context).To(&i32_value)) return;
1705 1000 : receiver->SetI32(i32_value);
1706 : break;
1707 : }
1708 : case i::wasm::kWasmI64: {
1709 32 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1710 32 : if (enabled_features.bigint) {
1711 : v8::Local<v8::BigInt> bigint_value;
1712 48 : if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
1713 32 : receiver->SetI64(bigint_value->Int64Value());
1714 : } else {
1715 8 : thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
1716 : }
1717 24 : break;
1718 : }
1719 : case i::wasm::kWasmF32: {
1720 : double f64_value = 0;
1721 1936 : if (!args[0]->NumberValue(context).To(&f64_value)) return;
1722 1936 : receiver->SetF32(static_cast<float>(f64_value));
1723 : break;
1724 : }
1725 : case i::wasm::kWasmF64: {
1726 : double f64_value = 0;
1727 880 : if (!args[0]->NumberValue(context).To(&f64_value)) return;
1728 440 : receiver->SetF64(f64_value);
1729 : break;
1730 : }
1731 : case i::wasm::kWasmAnyRef:
1732 : case i::wasm::kWasmExceptRef: {
1733 72 : receiver->SetAnyRef(Utils::OpenHandle(*args[0]));
1734 72 : break;
1735 : }
1736 : case i::wasm::kWasmAnyFunc: {
1737 24 : if (!receiver->SetAnyFunc(i_isolate, Utils::OpenHandle(*args[0]))) {
1738 : thrower.TypeError(
1739 : "value of an anyfunc reference must be either null or an "
1740 8 : "exported function");
1741 : }
1742 : break;
1743 : }
1744 : default:
1745 0 : UNREACHABLE();
1746 : }
1747 : }
1748 :
1749 : // WebAssembly.Global.type(WebAssembly.Global) -> GlobalType
1750 88 : void WebAssemblyGlobalGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1751 : v8::Isolate* isolate = args.GetIsolate();
1752 144 : HandleScope scope(isolate);
1753 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1754 56 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()");
1755 :
1756 88 : auto maybe_global = GetFirstArgumentAsGlobal(args, &thrower);
1757 120 : if (thrower.error()) return;
1758 : i::Handle<i::WasmGlobalObject> global = maybe_global.ToHandleChecked();
1759 56 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1760 :
1761 168 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1762 : v8_str(isolate, "mutable"),
1763 112 : v8::Boolean::New(isolate, global->is_mutable()))
1764 : .IsJust()) {
1765 : return;
1766 : }
1767 :
1768 : Local<String> type;
1769 56 : switch (global->type()) {
1770 : case i::wasm::kWasmI32: {
1771 : type = v8_str(isolate, "i32");
1772 16 : break;
1773 : }
1774 : case i::wasm::kWasmI64: {
1775 : type = v8_str(isolate, "i64");
1776 8 : break;
1777 : }
1778 : case i::wasm::kWasmF32: {
1779 : type = v8_str(isolate, "f32");
1780 8 : break;
1781 : }
1782 : case i::wasm::kWasmF64: {
1783 : type = v8_str(isolate, "f64");
1784 8 : break;
1785 : }
1786 : case i::wasm::kWasmAnyRef: {
1787 : type = v8_str(isolate, "anyref");
1788 16 : break;
1789 : }
1790 : default:
1791 0 : UNREACHABLE();
1792 : }
1793 168 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1794 112 : v8_str(isolate, "value"), type)
1795 : .IsJust()) {
1796 : return;
1797 : }
1798 :
1799 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1800 : return_value.Set(ret);
1801 : }
1802 :
1803 : } // namespace
1804 :
1805 : // TODO(titzer): we use the API to create the function template because the
1806 : // internal guts are too ugly to replicate here.
1807 1691374 : static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
1808 : i::Isolate* i_isolate, FunctionCallback func) {
1809 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1810 1691374 : Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
1811 1691377 : templ->ReadOnlyPrototype();
1812 1691375 : return v8::Utils::OpenHandle(*templ);
1813 : }
1814 :
1815 : static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
1816 : i::Isolate* i_isolate) {
1817 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1818 402847 : Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
1819 : return v8::Utils::OpenHandle(*templ);
1820 : }
1821 :
1822 : namespace internal {
1823 :
1824 1691377 : Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
1825 : FunctionCallback func) {
1826 1691377 : Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
1827 : Handle<JSFunction> function =
1828 3382731 : ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
1829 : DCHECK(function->shared()->HasSharedName());
1830 1691356 : return function;
1831 : }
1832 :
1833 1288741 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
1834 : const char* str, FunctionCallback func,
1835 : int length = 0,
1836 : PropertyAttributes attributes = NONE) {
1837 : Handle<String> name = v8_str(isolate, str);
1838 1288740 : Handle<JSFunction> function = CreateFunc(isolate, name, func);
1839 : function->shared()->set_length(length);
1840 1288731 : JSObject::AddProperty(isolate, object, name, function, attributes);
1841 1288735 : return function;
1842 : }
1843 :
1844 0 : Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
1845 : Handle<JSObject> object,
1846 : const char* str,
1847 : FunctionCallback func) {
1848 402849 : return InstallFunc(isolate, object, str, func, 1, DONT_ENUM);
1849 : }
1850 :
1851 322106 : Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
1852 644218 : return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
1853 322112 : .ToHandleChecked();
1854 : }
1855 :
1856 241577 : void InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str,
1857 : FunctionCallback func) {
1858 : Handle<String> name = v8_str(isolate, str);
1859 : Handle<JSFunction> function =
1860 241579 : CreateFunc(isolate, GetterName(isolate, name), func);
1861 :
1862 241582 : Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
1863 : Utils::ToLocal(function),
1864 241580 : Local<Function>(), v8::None);
1865 241582 : }
1866 :
1867 80527 : Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
1868 161055 : return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
1869 80528 : .ToHandleChecked();
1870 : }
1871 :
1872 80527 : void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
1873 : const char* str, FunctionCallback getter,
1874 : FunctionCallback setter) {
1875 : Handle<String> name = v8_str(isolate, str);
1876 : Handle<JSFunction> getter_func =
1877 80527 : CreateFunc(isolate, GetterName(isolate, name), getter);
1878 : Handle<JSFunction> setter_func =
1879 80527 : CreateFunc(isolate, SetterName(isolate, name), setter);
1880 : setter_func->shared()->set_length(1);
1881 :
1882 : v8::PropertyAttribute attributes = v8::None;
1883 :
1884 80528 : Utils::ToLocal(object)->SetAccessorProperty(
1885 : Utils::ToLocal(name), Utils::ToLocal(getter_func),
1886 80528 : Utils::ToLocal(setter_func), attributes);
1887 80528 : }
1888 :
1889 : // Assigns a dummy instance template to the given constructor function. Used to
1890 : // make sure the implicit receivers for the constructors in this file have an
1891 : // instance type different from the internal one, they allocate the resulting
1892 : // object explicitly and ignore implicit receiver.
1893 402847 : void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
1894 : Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
1895 402848 : FunctionTemplateInfo::SetInstanceTemplate(
1896 : isolate, handle(fun->shared()->get_api_func_data(), isolate),
1897 402850 : instance_template);
1898 402848 : }
1899 :
1900 : // static
1901 1174826 : void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
1902 1174826 : Handle<JSGlobalObject> global = isolate->global_object();
1903 : Handle<Context> context(global->native_context(), isolate);
1904 : // Install the JS API once only.
1905 : Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
1906 1174829 : if (!prev->IsUndefined(isolate)) {
1907 : DCHECK(prev->IsJSFunction());
1908 1094302 : return;
1909 : }
1910 :
1911 : Factory* factory = isolate->factory();
1912 :
1913 : // Setup WebAssembly
1914 : Handle<String> name = v8_str(isolate, "WebAssembly");
1915 : NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
1916 80527 : name, isolate->strict_function_map(), LanguageMode::kStrict);
1917 80525 : Handle<JSFunction> cons = factory->NewFunction(args);
1918 161054 : JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
1919 : Handle<JSObject> webassembly =
1920 80528 : factory->NewJSObject(cons, AllocationType::kOld);
1921 :
1922 : PropertyAttributes ro_attributes =
1923 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
1924 80528 : JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
1925 80528 : name, ro_attributes);
1926 80528 : InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
1927 80528 : InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
1928 80527 : InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
1929 :
1930 80527 : if (isolate->wasm_streaming_callback() != nullptr) {
1931 : InstallFunc(isolate, webassembly, "compileStreaming",
1932 24 : WebAssemblyCompileStreaming, 1);
1933 : InstallFunc(isolate, webassembly, "instantiateStreaming",
1934 24 : WebAssemblyInstantiateStreaming, 1);
1935 : }
1936 :
1937 : // Expose the API on the global object if configured to do so.
1938 80528 : if (exposed_on_global_object) {
1939 80503 : JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM);
1940 : }
1941 :
1942 : // Setup Module
1943 : Handle<JSFunction> module_constructor =
1944 : InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule);
1945 80528 : context->set_wasm_module_constructor(*module_constructor);
1946 80528 : SetDummyInstanceTemplate(isolate, module_constructor);
1947 80527 : JSFunction::EnsureHasInitialMap(module_constructor);
1948 : Handle<JSObject> module_proto(
1949 161055 : JSObject::cast(module_constructor->instance_prototype()), isolate);
1950 : i::Handle<i::Map> module_map =
1951 80527 : isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
1952 80528 : JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
1953 : InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
1954 80528 : 1);
1955 : InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
1956 80527 : 1);
1957 : InstallFunc(isolate, module_constructor, "customSections",
1958 80527 : WebAssemblyModuleCustomSections, 2);
1959 80528 : JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
1960 80527 : v8_str(isolate, "WebAssembly.Module"), ro_attributes);
1961 :
1962 : // Setup Instance
1963 : Handle<JSFunction> instance_constructor = InstallConstructorFunc(
1964 : isolate, webassembly, "Instance", WebAssemblyInstance);
1965 80528 : context->set_wasm_instance_constructor(*instance_constructor);
1966 80527 : SetDummyInstanceTemplate(isolate, instance_constructor);
1967 80527 : JSFunction::EnsureHasInitialMap(instance_constructor);
1968 : Handle<JSObject> instance_proto(
1969 161054 : JSObject::cast(instance_constructor->instance_prototype()), isolate);
1970 : i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
1971 80527 : i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
1972 80528 : JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
1973 : InstallGetter(isolate, instance_proto, "exports",
1974 80528 : WebAssemblyInstanceGetExports);
1975 80527 : JSObject::AddProperty(isolate, instance_proto,
1976 : factory->to_string_tag_symbol(),
1977 80527 : v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
1978 :
1979 : // The context is not set up completely yet. That's why we cannot use
1980 : // {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
1981 80527 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1982 :
1983 : // Setup Table
1984 : Handle<JSFunction> table_constructor =
1985 : InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable);
1986 80525 : context->set_wasm_table_constructor(*table_constructor);
1987 80525 : SetDummyInstanceTemplate(isolate, table_constructor);
1988 80526 : JSFunction::EnsureHasInitialMap(table_constructor);
1989 : Handle<JSObject> table_proto(
1990 161052 : JSObject::cast(table_constructor->instance_prototype()), isolate);
1991 : i::Handle<i::Map> table_map =
1992 80526 : isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
1993 80527 : JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
1994 80526 : InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
1995 80528 : InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
1996 80527 : InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
1997 80526 : InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
1998 80525 : if (enabled_features.type_reflection) {
1999 16 : InstallFunc(isolate, table_constructor, "type", WebAssemblyTableGetType, 1);
2000 : }
2001 80527 : JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
2002 80525 : v8_str(isolate, "WebAssembly.Table"), ro_attributes);
2003 :
2004 : // Setup Memory
2005 : Handle<JSFunction> memory_constructor =
2006 : InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory);
2007 80528 : context->set_wasm_memory_constructor(*memory_constructor);
2008 80528 : SetDummyInstanceTemplate(isolate, memory_constructor);
2009 80528 : JSFunction::EnsureHasInitialMap(memory_constructor);
2010 : Handle<JSObject> memory_proto(
2011 161056 : JSObject::cast(memory_constructor->instance_prototype()), isolate);
2012 : i::Handle<i::Map> memory_map =
2013 80528 : isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
2014 80527 : JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
2015 80528 : InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
2016 80526 : InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
2017 80528 : if (enabled_features.type_reflection) {
2018 : InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryGetType,
2019 16 : 1);
2020 : }
2021 80528 : JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
2022 80528 : v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
2023 :
2024 : // Setup Global
2025 : Handle<JSFunction> global_constructor =
2026 : InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal);
2027 80527 : context->set_wasm_global_constructor(*global_constructor);
2028 80527 : SetDummyInstanceTemplate(isolate, global_constructor);
2029 80528 : JSFunction::EnsureHasInitialMap(global_constructor);
2030 : Handle<JSObject> global_proto(
2031 161055 : JSObject::cast(global_constructor->instance_prototype()), isolate);
2032 : i::Handle<i::Map> global_map =
2033 80527 : isolate->factory()->NewMap(i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
2034 80527 : JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
2035 80527 : InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
2036 : InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
2037 80527 : WebAssemblyGlobalSetValue);
2038 80526 : if (enabled_features.type_reflection) {
2039 : InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalGetType,
2040 16 : 1);
2041 : }
2042 80527 : JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
2043 80527 : v8_str(isolate, "WebAssembly.Global"), ro_attributes);
2044 :
2045 : // Setup Exception
2046 80527 : if (enabled_features.eh) {
2047 : Handle<JSFunction> exception_constructor = InstallConstructorFunc(
2048 : isolate, webassembly, "Exception", WebAssemblyException);
2049 212 : context->set_wasm_exception_constructor(*exception_constructor);
2050 212 : SetDummyInstanceTemplate(isolate, exception_constructor);
2051 212 : JSFunction::EnsureHasInitialMap(exception_constructor);
2052 : Handle<JSObject> exception_proto(
2053 424 : JSObject::cast(exception_constructor->instance_prototype()), isolate);
2054 : i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
2055 212 : i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
2056 212 : JSFunction::SetInitialMap(exception_constructor, exception_map,
2057 212 : exception_proto);
2058 : }
2059 :
2060 : // Setup errors
2061 : Handle<JSFunction> compile_error(
2062 241581 : isolate->native_context()->wasm_compile_error_function(), isolate);
2063 80528 : JSObject::AddProperty(isolate, webassembly,
2064 : isolate->factory()->CompileError_string(),
2065 80527 : compile_error, DONT_ENUM);
2066 : Handle<JSFunction> link_error(
2067 241584 : isolate->native_context()->wasm_link_error_function(), isolate);
2068 80527 : JSObject::AddProperty(isolate, webassembly,
2069 : isolate->factory()->LinkError_string(), link_error,
2070 80528 : DONT_ENUM);
2071 : Handle<JSFunction> runtime_error(
2072 241580 : isolate->native_context()->wasm_runtime_error_function(), isolate);
2073 80528 : JSObject::AddProperty(isolate, webassembly,
2074 : isolate->factory()->RuntimeError_string(),
2075 80526 : runtime_error, DONT_ENUM);
2076 : }
2077 :
2078 : #undef ASSIGN
2079 : #undef EXTRACT_THIS
2080 :
2081 : } // namespace internal
2082 120216 : } // namespace v8
|