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 192 : class WasmStreaming::WasmStreamingImpl {
37 : public:
38 96 : WasmStreamingImpl(
39 : Isolate* isolate,
40 : std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
41 96 : : isolate_(isolate), resolver_(std::move(resolver)) {
42 96 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
43 96 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
44 288 : streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
45 : i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
46 : resolver_);
47 96 : }
48 :
49 : void OnBytesReceived(const uint8_t* bytes, size_t size) {
50 64 : streaming_decoder_->OnBytesReceived(i::VectorOf(bytes, size));
51 : }
52 64 : void Finish() { streaming_decoder_->Finish(); }
53 :
54 24 : void Abort(MaybeLocal<Value> exception) {
55 24 : i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
56 24 : 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 24 : if (exception.IsEmpty()) return;
62 :
63 : resolver_->OnCompilationFailed(
64 40 : 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 24 : 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 92 : 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 92 : 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 109824010 : 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 54912005 : if (isolate()->has_scheduled_exception()) {
163 1772 : Reset();
164 54910233 : } else if (isolate()->has_pending_exception()) {
165 48 : Reset();
166 48 : isolate()->OptionalRescheduleException(false);
167 54910185 : } else if (error()) {
168 47384 : isolate()->ScheduleThrow(*Reify());
169 : }
170 54912006 : }
171 :
172 : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
173 2174401 : 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 392035 : 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 282759 : 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 282759 : if (source->IsArrayBuffer()) {
207 : // A raw array buffer was passed.
208 : Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
209 253864 : ArrayBuffer::Contents contents = buffer->GetContents();
210 :
211 : start = reinterpret_cast<const uint8_t*>(contents.Data());
212 : length = contents.ByteLength();
213 253864 : *is_shared = buffer->IsSharedArrayBuffer();
214 28896 : } else if (source->IsTypedArray()) {
215 : // A TypedArray was passed.
216 : Local<TypedArray> array = Local<TypedArray>::Cast(source);
217 28416 : Local<ArrayBuffer> buffer = array->Buffer();
218 :
219 28413 : ArrayBuffer::Contents contents = buffer->GetContents();
220 :
221 : start =
222 28416 : reinterpret_cast<const uint8_t*>(contents.Data()) + array->ByteOffset();
223 28416 : length = array->ByteLength();
224 28416 : *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 282761 : if (length == 0) {
230 780 : thrower->CompileError("BufferSource argument is empty");
231 : }
232 282761 : 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 282761 : if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
237 281957 : return i::wasm::ModuleWireBytes(start, start + length);
238 : }
239 :
240 132581 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
241 : ErrorThrower* thrower) {
242 132581 : if (arg->IsUndefined()) return {};
243 :
244 125039 : 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 124799 : 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 848 : AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
258 1696 : : promise_(isolate->global_handles()->Create(*promise)) {
259 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
260 848 : kGlobalPromiseHandle);
261 848 : }
262 :
263 1696 : ~AsyncCompilationResolver() override {
264 848 : i::GlobalHandles::Destroy(promise_.location());
265 808 : }
266 :
267 349 : void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
268 349 : if (finished_) return;
269 349 : finished_ = true;
270 : i::MaybeHandle<i::Object> promise_result =
271 349 : i::JSPromise::Resolve(promise_, result);
272 349 : CHECK_EQ(promise_result.is_null(),
273 : promise_->GetIsolate()->has_pending_exception());
274 : }
275 :
276 484 : void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
277 484 : if (finished_) return;
278 484 : finished_ = true;
279 : i::MaybeHandle<i::Object> promise_result =
280 484 : i::JSPromise::Reject(promise_, error_reason);
281 484 : 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 7382 : InstantiateModuleResultResolver(i::Isolate* isolate,
300 : i::Handle<i::JSPromise> promise)
301 14764 : : promise_(isolate->global_handles()->Create(*promise)) {
302 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
303 7382 : kGlobalPromiseHandle);
304 7382 : }
305 :
306 14764 : ~InstantiateModuleResultResolver() override {
307 7382 : i::GlobalHandles::Destroy(promise_.location());
308 7382 : }
309 :
310 120 : void OnInstantiationSucceeded(
311 : i::Handle<i::WasmInstanceObject> instance) override {
312 : i::MaybeHandle<i::Object> promise_result =
313 120 : i::JSPromise::Resolve(promise_, instance);
314 120 : CHECK_EQ(promise_result.is_null(),
315 : promise_->GetIsolate()->has_pending_exception());
316 120 : }
317 :
318 5362 : void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
319 : i::MaybeHandle<i::Object> promise_result =
320 5362 : i::JSPromise::Reject(promise_, error_reason);
321 5362 : CHECK_EQ(promise_result.is_null(),
322 : promise_->GetIsolate()->has_pending_exception());
323 5362 : }
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 1852 : 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 7408 : module_(isolate_->global_handles()->Create(*module)) {
345 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
346 1852 : kGlobalPromiseHandle);
347 : i::GlobalHandles::AnnotateStrongRetainer(module_.location(),
348 1852 : kGlobalModuleHandle);
349 1852 : }
350 :
351 3704 : ~InstantiateBytesResultResolver() override {
352 1852 : i::GlobalHandles::Destroy(promise_.location());
353 1852 : i::GlobalHandles::Destroy(module_.location());
354 1852 : }
355 :
356 1204 : 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 1204 : isolate_->factory()->NewJSObject(isolate_->object_function());
362 :
363 : i::Handle<i::String> instance_name =
364 1204 : isolate_->factory()
365 2408 : ->NewStringFromOneByte(i::StaticCharVector("instance"))
366 : .ToHandleChecked();
367 :
368 : i::Handle<i::String> module_name =
369 1204 : isolate_->factory()
370 2408 : ->NewStringFromOneByte(i::StaticCharVector("module"))
371 : .ToHandleChecked();
372 :
373 2408 : i::JSObject::AddProperty(isolate_, result, instance_name, instance,
374 1204 : i::NONE);
375 1204 : i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);
376 :
377 : i::MaybeHandle<i::Object> promise_result =
378 1204 : i::JSPromise::Resolve(promise_, result);
379 2408 : CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
380 1204 : }
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 1900 : 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 784 : : isolate_->global_handles()->Create(
415 5700 : *maybe_imports.ToHandleChecked())) {
416 : i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
417 1900 : kGlobalPromiseHandle);
418 1900 : if (!maybe_imports_.is_null()) {
419 : i::GlobalHandles::AnnotateStrongRetainer(
420 784 : maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle);
421 : }
422 1900 : }
423 :
424 3800 : ~AsyncInstantiateCompileResultResolver() override {
425 1900 : i::GlobalHandles::Destroy(promise_.location());
426 1900 : if (!maybe_imports_.is_null()) {
427 784 : i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
428 : }
429 3800 : }
430 :
431 1852 : void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
432 1852 : if (finished_) return;
433 1852 : finished_ = true;
434 3704 : isolate_->wasm_engine()->AsyncInstantiate(
435 : isolate_,
436 3704 : base::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
437 : result),
438 1852 : result, maybe_imports_);
439 : }
440 :
441 48 : void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
442 48 : if (finished_) return;
443 48 : finished_ = true;
444 : i::MaybeHandle<i::Object> promise_result =
445 48 : i::JSPromise::Reject(promise_, error_reason);
446 96 : 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 24564 : bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context,
474 : ErrorThrower* thrower, uint32_t* res) {
475 : double double_number;
476 :
477 49128 : 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 24500 : 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 23924 : 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 23556 : 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 23276 : *res = static_cast<uint32_t>(double_number);
499 23276 : return true;
500 : }
501 : } // namespace
502 :
503 : // WebAssembly.compile(bytes) -> Promise
504 808 : 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 1372 : HandleScope scope(isolate);
509 564 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
510 :
511 1616 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
512 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
513 : }
514 :
515 808 : Local<Context> context = isolate->GetCurrentContext();
516 1860 : ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
517 808 : 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 1616 : new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));
523 :
524 808 : bool is_shared = false;
525 808 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
526 808 : if (thrower.error()) {
527 244 : resolver->OnCompilationFailed(thrower.Reify());
528 : return;
529 : }
530 : // Asynchronous compilation handles copying wire bytes if necessary.
531 564 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
532 1128 : i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
533 564 : std::move(resolver), bytes, is_shared);
534 : }
535 :
536 56 : void WasmStreamingCallbackForTesting(
537 : const v8::FunctionCallbackInfo<v8::Value>& args) {
538 : v8::Isolate* isolate = args.GetIsolate();
539 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
540 :
541 112 : HandleScope scope(isolate);
542 56 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
543 :
544 : std::shared_ptr<v8::WasmStreaming> streaming =
545 56 : v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
546 :
547 56 : bool is_shared = false;
548 : i::wasm::ModuleWireBytes bytes =
549 56 : GetFirstArgumentAsBytes(args, &thrower, &is_shared);
550 56 : if (thrower.error()) {
551 0 : streaming->Abort(Utils::ToLocal(thrower.Reify()));
552 : return;
553 : }
554 : streaming->OnBytesReceived(bytes.start(), bytes.length());
555 : streaming->Finish();
556 56 : CHECK(!thrower.error());
557 : }
558 :
559 16 : void WasmStreamingPromiseFailedCallback(
560 : const v8::FunctionCallbackInfo<v8::Value>& args) {
561 : std::shared_ptr<v8::WasmStreaming> streaming =
562 16 : v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
563 : streaming->Abort(args[0]);
564 16 : }
565 :
566 : // WebAssembly.compileStreaming(Promise<Response>) -> Promise
567 40 : void WebAssemblyCompileStreaming(
568 : const v8::FunctionCallbackInfo<v8::Value>& args) {
569 : v8::Isolate* isolate = args.GetIsolate();
570 40 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
571 80 : HandleScope scope(isolate);
572 80 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");
573 40 : Local<Context> context = isolate->GetCurrentContext();
574 :
575 : // Create and assign the return value of this function.
576 80 : ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
577 40 : Local<Promise> promise = result_resolver->GetPromise();
578 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
579 : return_value.Set(promise);
580 :
581 : // Prepare the CompilationResultResolver for the compilation.
582 : auto resolver = std::make_shared<AsyncCompilationResolver>(
583 80 : i_isolate, Utils::OpenHandle(*promise));
584 :
585 80 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
586 0 : thrower.CompileError("Wasm code generation disallowed by embedder");
587 0 : resolver->OnCompilationFailed(thrower.Reify());
588 0 : return;
589 : }
590 :
591 : // Allocate the streaming decoder in a Managed so we can pass it to the
592 : // embedder.
593 : i::Handle<i::Managed<WasmStreaming>> data =
594 : i::Managed<WasmStreaming>::Allocate(
595 : i_isolate, 0,
596 80 : base::make_unique<WasmStreaming::WasmStreamingImpl>(isolate,
597 40 : resolver));
598 :
599 : DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
600 80 : ASSIGN(
601 : v8::Function, compile_callback,
602 : v8::Function::New(context, i_isolate->wasm_streaming_callback(),
603 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
604 80 : ASSIGN(
605 : v8::Function, reject_callback,
606 : v8::Function::New(context, WasmStreamingPromiseFailedCallback,
607 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
608 :
609 : // The parameter may be of type {Response} or of type {Promise<Response>}.
610 : // Treat either case of parameter as Promise.resolve(parameter)
611 : // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
612 :
613 : // Ending with:
614 : // return Promise.resolve(parameter).then(compile_callback);
615 80 : ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
616 80 : if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
617 :
618 : // We do not have any use of the result here. The {compile_callback} will
619 : // start streaming compilation, which will eventually resolve the promise we
620 : // set as result value.
621 80 : USE(input_resolver->GetPromise()->Then(context, compile_callback,
622 : reject_callback));
623 : }
624 :
625 : // WebAssembly.validate(bytes) -> bool
626 128040 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
627 : v8::Isolate* isolate = args.GetIsolate();
628 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
629 255888 : HandleScope scope(isolate);
630 127848 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");
631 :
632 128040 : bool is_shared = false;
633 128040 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
634 :
635 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
636 :
637 128040 : if (thrower.error()) {
638 192 : if (thrower.wasm_error()) thrower.Reset(); // Clear error.
639 : return_value.Set(v8::False(isolate));
640 192 : return;
641 : }
642 :
643 127848 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
644 : bool validated = false;
645 127848 : if (is_shared) {
646 : // Make a copy of the wire bytes to avoid concurrent modification.
647 0 : std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
648 : memcpy(copy.get(), bytes.start(), bytes.length());
649 : i::wasm::ModuleWireBytes bytes_copy(copy.get(),
650 0 : copy.get() + bytes.length());
651 : validated = i_isolate->wasm_engine()->SyncValidate(
652 0 : i_isolate, enabled_features, bytes_copy);
653 : } else {
654 : // The wire bytes are not shared, OK to use them directly.
655 : validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
656 127848 : enabled_features, bytes);
657 : }
658 :
659 : return_value.Set(Boolean::New(isolate, validated));
660 : }
661 :
662 : // new WebAssembly.Module(bytes) -> WebAssembly.Module
663 151969 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
664 : v8::Isolate* isolate = args.GetIsolate();
665 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
666 168889 : if (i_isolate->wasm_module_callback()(args)) return;
667 :
668 287014 : HandleScope scope(isolate);
669 135053 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
670 :
671 151964 : if (!args.IsConstructCall()) {
672 32 : thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
673 32 : return;
674 : }
675 303862 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
676 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
677 24 : return;
678 : }
679 :
680 151908 : bool is_shared = false;
681 151908 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
682 :
683 151909 : if (thrower.error()) {
684 : return;
685 : }
686 151645 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
687 : i::MaybeHandle<i::Object> module_obj;
688 151641 : if (is_shared) {
689 : // Make a copy of the wire bytes to avoid concurrent modification.
690 0 : std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
691 : memcpy(copy.get(), bytes.start(), bytes.length());
692 : i::wasm::ModuleWireBytes bytes_copy(copy.get(),
693 0 : copy.get() + bytes.length());
694 : module_obj = i_isolate->wasm_engine()->SyncCompile(
695 0 : i_isolate, enabled_features, &thrower, bytes_copy);
696 : } else {
697 : // The wire bytes are not shared, OK to use them directly.
698 : module_obj = i_isolate->wasm_engine()->SyncCompile(
699 151641 : i_isolate, enabled_features, &thrower, bytes);
700 : }
701 :
702 151644 : if (module_obj.is_null()) return;
703 :
704 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
705 : return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
706 : }
707 :
708 : // WebAssembly.Module.imports(module) -> Array<Import>
709 248 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
710 392 : HandleScope scope(args.GetIsolate());
711 : v8::Isolate* isolate = args.GetIsolate();
712 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
713 144 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
714 :
715 248 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
716 352 : if (thrower.error()) return;
717 144 : auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
718 : args.GetReturnValue().Set(Utils::ToLocal(imports));
719 : }
720 :
721 : // WebAssembly.Module.exports(module) -> Array<Export>
722 240 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
723 376 : HandleScope scope(args.GetIsolate());
724 : v8::Isolate* isolate = args.GetIsolate();
725 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
726 136 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
727 :
728 240 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
729 344 : if (thrower.error()) return;
730 136 : auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
731 : args.GetReturnValue().Set(Utils::ToLocal(exports));
732 : }
733 :
734 : // WebAssembly.Module.customSections(module, name) -> Array<Section>
735 376 : void WebAssemblyModuleCustomSections(
736 : const v8::FunctionCallbackInfo<v8::Value>& args) {
737 624 : HandleScope scope(args.GetIsolate());
738 : v8::Isolate* isolate = args.GetIsolate();
739 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
740 : ScheduledErrorThrower thrower(i_isolate,
741 248 : "WebAssembly.Module.customSections()");
742 :
743 376 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
744 504 : if (thrower.error()) return;
745 :
746 264 : if (args[1]->IsUndefined()) {
747 8 : thrower.TypeError("Argument 1 is required");
748 8 : return;
749 : }
750 :
751 : i::MaybeHandle<i::Object> maybe_name =
752 256 : i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
753 : i::Handle<i::Object> name;
754 256 : if (!maybe_name.ToHandle(&name)) return;
755 : auto custom_sections =
756 : i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
757 248 : i::Handle<i::String>::cast(name), &thrower);
758 248 : if (thrower.error()) return;
759 : args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
760 : }
761 :
762 129824 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
763 : Local<Value> module,
764 : Local<Value> ffi) {
765 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
766 :
767 : i::MaybeHandle<i::Object> instance_object;
768 : {
769 129746 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
770 :
771 : // TODO(ahaas): These checks on the module should not be necessary here They
772 : // are just a workaround for https://crbug.com/837417.
773 : i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
774 129824 : if (!module_obj->IsWasmModuleObject()) {
775 0 : thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
776 0 : return {};
777 : }
778 :
779 : i::MaybeHandle<i::JSReceiver> maybe_imports =
780 129824 : GetValueAsImports(ffi, &thrower);
781 129825 : if (thrower.error()) return {};
782 :
783 : instance_object = i_isolate->wasm_engine()->SyncInstantiate(
784 : i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
785 129745 : maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
786 : }
787 :
788 : DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
789 129747 : if (instance_object.is_null()) return {};
790 128135 : return Utils::ToLocal(instance_object.ToHandleChecked());
791 : }
792 :
793 : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
794 130002 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
795 : Isolate* isolate = args.GetIsolate();
796 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
797 : i_isolate->CountUsage(
798 130002 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
799 :
800 259827 : HandleScope scope(args.GetIsolate());
801 130176 : if (i_isolate->wasm_instance_callback()(args)) return;
802 :
803 129827 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
804 129993 : if (!args.IsConstructCall()) {
805 24 : thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
806 24 : return;
807 : }
808 :
809 129969 : GetFirstArgumentAsModule(args, &thrower);
810 129968 : if (thrower.error()) return;
811 :
812 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
813 : // We'll check for that in WebAssemblyInstantiateImpl.
814 129825 : Local<Value> data = args[1];
815 :
816 : Local<Value> instance;
817 259652 : if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
818 : args.GetReturnValue().Set(instance);
819 : }
820 : }
821 :
822 56 : void WebAssemblyInstantiateStreaming(
823 : const v8::FunctionCallbackInfo<v8::Value>& args) {
824 56 : v8::Isolate* isolate = args.GetIsolate();
825 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
826 : i_isolate->CountUsage(
827 56 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
828 :
829 112 : HandleScope scope(isolate);
830 56 : Local<Context> context = isolate->GetCurrentContext();
831 : ScheduledErrorThrower thrower(i_isolate,
832 56 : "WebAssembly.instantiateStreaming()");
833 :
834 : // Create and assign the return value of this function.
835 112 : ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
836 56 : Local<Promise> promise = result_resolver->GetPromise();
837 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
838 : return_value.Set(promise);
839 :
840 : // Create an InstantiateResultResolver in case there is an issue with the
841 : // passed parameters.
842 : std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
843 : new InstantiateModuleResultResolver(i_isolate,
844 56 : Utils::OpenHandle(*promise)));
845 :
846 112 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
847 0 : thrower.CompileError("Wasm code generation disallowed by embedder");
848 0 : resolver->OnInstantiationFailed(thrower.Reify());
849 0 : return;
850 : }
851 :
852 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
853 56 : Local<Value> ffi = args[1];
854 : i::MaybeHandle<i::JSReceiver> maybe_imports =
855 56 : GetValueAsImports(ffi, &thrower);
856 :
857 56 : if (thrower.error()) {
858 0 : resolver->OnInstantiationFailed(thrower.Reify());
859 0 : return;
860 : }
861 :
862 : // We start compilation now, we have no use for the
863 : // {InstantiationResultResolver}.
864 : resolver.reset();
865 :
866 : std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
867 : new AsyncInstantiateCompileResultResolver(
868 112 : i_isolate, Utils::OpenHandle(*promise), maybe_imports));
869 :
870 : // Allocate the streaming decoder in a Managed so we can pass it to the
871 : // embedder.
872 : i::Handle<i::Managed<WasmStreaming>> data =
873 : i::Managed<WasmStreaming>::Allocate(
874 : i_isolate, 0,
875 112 : base::make_unique<WasmStreaming::WasmStreamingImpl>(
876 56 : isolate, compilation_resolver));
877 :
878 : DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
879 112 : ASSIGN(
880 : v8::Function, compile_callback,
881 : v8::Function::New(context, i_isolate->wasm_streaming_callback(),
882 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
883 112 : ASSIGN(
884 : v8::Function, reject_callback,
885 : v8::Function::New(context, WasmStreamingPromiseFailedCallback,
886 : Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
887 :
888 : // The parameter may be of type {Response} or of type {Promise<Response>}.
889 : // Treat either case of parameter as Promise.resolve(parameter)
890 : // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments
891 :
892 : // Ending with:
893 : // return Promise.resolve(parameter).then(compile_callback);
894 112 : ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
895 112 : if (!input_resolver->Resolve(context, args[0]).IsJust()) return;
896 :
897 : // We do not have any use of the result here. The {compile_callback} will
898 : // start streaming compilation, which will eventually resolve the promise we
899 : // set as result value.
900 112 : USE(input_resolver->GetPromise()->Then(context, compile_callback,
901 : reject_callback));
902 : }
903 :
904 : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
905 : // WebAssembly.instantiate(bytes, imports) ->
906 : // {module: WebAssembly.Module, instance: WebAssembly.Instance}
907 7326 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
908 : v8::Isolate* isolate = args.GetIsolate();
909 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
910 : i_isolate->CountUsage(
911 7326 : v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);
912 :
913 1820 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
914 :
915 9146 : HandleScope scope(isolate);
916 :
917 7326 : Local<Context> context = isolate->GetCurrentContext();
918 :
919 20158 : ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
920 7326 : Local<Promise> promise = promise_resolver->GetPromise();
921 : args.GetReturnValue().Set(promise);
922 :
923 : std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
924 : new InstantiateModuleResultResolver(i_isolate,
925 7326 : Utils::OpenHandle(*promise)));
926 :
927 : Local<Value> first_arg_value = args[0];
928 : i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
929 7326 : if (!first_arg->IsJSObject()) {
930 : thrower.TypeError(
931 4626 : "Argument 0 must be a buffer source or a WebAssembly.Module object");
932 4626 : resolver->OnInstantiationFailed(thrower.Reify());
933 4626 : return;
934 : }
935 :
936 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
937 2700 : Local<Value> ffi = args[1];
938 : i::MaybeHandle<i::JSReceiver> maybe_imports =
939 2700 : GetValueAsImports(ffi, &thrower);
940 :
941 2700 : if (thrower.error()) {
942 160 : resolver->OnInstantiationFailed(thrower.Reify());
943 160 : return;
944 : }
945 :
946 2540 : if (first_arg->IsWasmModuleObject()) {
947 : i::Handle<i::WasmModuleObject> module_obj =
948 592 : i::Handle<i::WasmModuleObject>::cast(first_arg);
949 :
950 592 : i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
951 592 : module_obj, maybe_imports);
952 : return;
953 : }
954 :
955 1948 : bool is_shared = false;
956 1948 : auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
957 1948 : if (thrower.error()) {
958 104 : resolver->OnInstantiationFailed(thrower.Reify());
959 104 : return;
960 : }
961 :
962 : // We start compilation now, we have no use for the
963 : // {InstantiationResultResolver}.
964 : resolver.reset();
965 :
966 : std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
967 : new AsyncInstantiateCompileResultResolver(
968 3688 : i_isolate, Utils::OpenHandle(*promise), maybe_imports));
969 :
970 : // The first parameter is a buffer source, we have to check if we are allowed
971 : // to compile it.
972 3688 : if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
973 24 : thrower.CompileError("Wasm code generation disallowed by embedder");
974 24 : compilation_resolver->OnCompilationFailed(thrower.Reify());
975 : return;
976 : }
977 :
978 : // Asynchronous compilation handles copying wire bytes if necessary.
979 1820 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
980 3640 : i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
981 : std::move(compilation_resolver), bytes,
982 1820 : is_shared);
983 : }
984 :
985 8824 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
986 : Local<Context> context, v8::Local<v8::Value> value,
987 : i::Handle<i::String> property_name, int64_t* result,
988 : int64_t lower_bound, uint64_t upper_bound) {
989 : uint32_t number;
990 8824 : if (!EnforceUint32(property_name, value, context, thrower, &number)) {
991 : return false;
992 : }
993 8512 : if (number < lower_bound) {
994 : thrower->RangeError("Property '%s': value %" PRIu32
995 : " is below the lower bound %" PRIx64,
996 144 : property_name->ToCString().get(), number, lower_bound);
997 : return false;
998 : }
999 8464 : if (number > upper_bound) {
1000 : thrower->RangeError("Property '%s': value %" PRIu32
1001 : " is above the upper bound %" PRIu64,
1002 192 : property_name->ToCString().get(), number, upper_bound);
1003 : return false;
1004 : }
1005 :
1006 8400 : *result = static_cast<int64_t>(number);
1007 : return true;
1008 : }
1009 :
1010 12878 : bool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
1011 : Local<Context> context,
1012 : Local<v8::Object> object,
1013 : Local<String> property, bool* has_property,
1014 : int64_t* result, int64_t lower_bound,
1015 : uint64_t upper_bound) {
1016 : v8::Local<v8::Value> value;
1017 25756 : if (!object->Get(context, property).ToLocal(&value)) {
1018 : return false;
1019 : }
1020 :
1021 : // Web IDL: dictionary presence
1022 : // https://heycam.github.io/webidl/#dfn-present
1023 12878 : if (value->IsUndefined()) {
1024 4054 : if (has_property != nullptr) *has_property = false;
1025 : return true;
1026 : }
1027 :
1028 8824 : if (has_property != nullptr) *has_property = true;
1029 8824 : i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property);
1030 :
1031 : return GetIntegerProperty(isolate, thrower, context, value, property_name,
1032 8824 : result, lower_bound, upper_bound);
1033 : }
1034 :
1035 : // Fetch 'initial' or 'minimum' property from object. If both are provided,
1036 : // 'initial' is used.
1037 : // TODO(aseemgarg): change behavior when the following bug is resolved:
1038 : // https://github.com/WebAssembly/js-types/issues/6
1039 6543 : bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
1040 : Local<Context> context,
1041 : Local<v8::Object> object, int64_t* result,
1042 : int64_t lower_bound, uint64_t upper_bound) {
1043 6543 : bool has_initial = false;
1044 6543 : if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
1045 : v8_str(isolate, "initial"), &has_initial,
1046 : result, lower_bound, upper_bound)) {
1047 : return false;
1048 : }
1049 6335 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1050 6335 : if (!has_initial && enabled_features.type_reflection) {
1051 32 : if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
1052 : v8_str(isolate, "minimum"), &has_initial,
1053 : result, lower_bound, upper_bound)) {
1054 : return false;
1055 : }
1056 : }
1057 6335 : if (!has_initial) {
1058 : // TODO(aseemgarg): update error message when the spec issue is resolved.
1059 32 : thrower->TypeError("Property 'initial' is required");
1060 32 : return false;
1061 : }
1062 : return true;
1063 : }
1064 :
1065 : // new WebAssembly.Table(args) -> WebAssembly.Table
1066 2164 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
1067 : v8::Isolate* isolate = args.GetIsolate();
1068 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1069 3872 : HandleScope scope(isolate);
1070 1708 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
1071 2164 : if (!args.IsConstructCall()) {
1072 24 : thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
1073 24 : return;
1074 : }
1075 2140 : if (!args[0]->IsObject()) {
1076 120 : thrower.TypeError("Argument 0 must be a table descriptor");
1077 120 : return;
1078 : }
1079 2020 : Local<Context> context = isolate->GetCurrentContext();
1080 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1081 : i::wasm::ValueType type;
1082 : // The descriptor's 'element'.
1083 : {
1084 : v8::MaybeLocal<v8::Value> maybe =
1085 2020 : descriptor->Get(context, v8_str(isolate, "element"));
1086 : v8::Local<v8::Value> value;
1087 2108 : if (!maybe.ToLocal(&value)) return;
1088 : v8::Local<v8::String> string;
1089 4040 : if (!value->ToString(context).ToLocal(&string)) return;
1090 2020 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1091 2020 : if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
1092 : type = i::wasm::kWasmAnyFunc;
1093 136 : } else if (enabled_features.anyref &&
1094 24 : string->StringEquals(v8_str(isolate, "anyref"))) {
1095 : type = i::wasm::kWasmAnyRef;
1096 : } else {
1097 88 : thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
1098 88 : return;
1099 : }
1100 : }
1101 :
1102 1932 : int64_t initial = 0;
1103 1932 : if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
1104 : &initial, 0,
1105 1932 : i::wasm::max_table_init_entries())) {
1106 : return;
1107 : }
1108 : // The descriptor's 'maximum'.
1109 1828 : int64_t maximum = -1;
1110 1828 : bool has_maximum = true;
1111 3656 : if (!GetOptionalIntegerProperty(
1112 : isolate, &thrower, context, descriptor, v8_str(isolate, "maximum"),
1113 1828 : &has_maximum, &maximum, initial, i::wasm::max_table_init_entries())) {
1114 : return;
1115 : }
1116 :
1117 : i::Handle<i::FixedArray> fixed_array;
1118 : i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
1119 : i_isolate, type, static_cast<uint32_t>(initial), has_maximum,
1120 1708 : static_cast<uint32_t>(maximum), &fixed_array);
1121 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1122 : return_value.Set(Utils::ToLocal(table_obj));
1123 : }
1124 :
1125 4755 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
1126 : v8::Isolate* isolate = args.GetIsolate();
1127 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1128 9118 : HandleScope scope(isolate);
1129 4363 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
1130 4755 : if (!args.IsConstructCall()) {
1131 24 : thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
1132 24 : return;
1133 : }
1134 4731 : if (!args[0]->IsObject()) {
1135 120 : thrower.TypeError("Argument 0 must be a memory descriptor");
1136 120 : return;
1137 : }
1138 4611 : Local<Context> context = isolate->GetCurrentContext();
1139 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1140 :
1141 4611 : int64_t initial = 0;
1142 4611 : if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
1143 4611 : &initial, 0, i::wasm::max_mem_pages())) {
1144 : return;
1145 : }
1146 : // The descriptor's 'maximum'.
1147 4475 : int64_t maximum = -1;
1148 8950 : if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
1149 : v8_str(isolate, "maximum"), nullptr, &maximum,
1150 : initial, i::wasm::kSpecMaxWasmMemoryPages)) {
1151 : return;
1152 : }
1153 :
1154 : bool is_shared_memory = false;
1155 4379 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1156 4379 : if (enabled_features.threads) {
1157 : // Shared property of descriptor
1158 : Local<String> shared_key = v8_str(isolate, "shared");
1159 : v8::MaybeLocal<v8::Value> maybe_value =
1160 297 : descriptor->Get(context, shared_key);
1161 : v8::Local<v8::Value> value;
1162 297 : if (maybe_value.ToLocal(&value)) {
1163 297 : is_shared_memory = value->BooleanValue(isolate);
1164 : }
1165 : // Throw TypeError if shared is true, and the descriptor has no "maximum"
1166 297 : if (is_shared_memory && maximum == -1) {
1167 : thrower.TypeError(
1168 8 : "If shared is true, maximum property should be defined.");
1169 : return;
1170 : }
1171 : }
1172 :
1173 : i::Handle<i::JSObject> memory_obj;
1174 8742 : if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
1175 : static_cast<uint32_t>(maximum),
1176 4371 : is_shared_memory)
1177 : .ToHandle(&memory_obj)) {
1178 8 : thrower.RangeError("could not allocate memory");
1179 8 : return;
1180 : }
1181 4363 : if (is_shared_memory) {
1182 : i::Handle<i::JSArrayBuffer> buffer(
1183 : i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(),
1184 : i_isolate);
1185 : Maybe<bool> result =
1186 249 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1187 249 : if (!result.FromJust()) {
1188 : thrower.TypeError(
1189 0 : "Status of setting SetIntegrityLevel of buffer is false.");
1190 : return;
1191 : }
1192 : }
1193 : args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
1194 : }
1195 :
1196 7560 : void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
1197 : v8::Isolate* isolate = args.GetIsolate();
1198 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1199 14864 : HandleScope scope(isolate);
1200 7304 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
1201 7560 : if (!args.IsConstructCall()) {
1202 8 : thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
1203 8 : return;
1204 : }
1205 7552 : if (!args[0]->IsObject()) {
1206 104 : thrower.TypeError("Argument 0 must be a global descriptor");
1207 104 : return;
1208 : }
1209 7448 : Local<Context> context = isolate->GetCurrentContext();
1210 : Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
1211 :
1212 : // The descriptor's 'mutable'.
1213 : bool is_mutable = false;
1214 : {
1215 : Local<String> mutable_key = v8_str(isolate, "mutable");
1216 7448 : v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
1217 : v8::Local<v8::Value> value;
1218 7448 : if (maybe.ToLocal(&value)) {
1219 7448 : is_mutable = value->BooleanValue(isolate);
1220 : }
1221 : }
1222 :
1223 : // The descriptor's type, called 'value'. It is called 'value' because this
1224 : // descriptor is planned to be re-used as the global's type for reflection,
1225 : // so calling it 'type' is redundant.
1226 : i::wasm::ValueType type;
1227 : {
1228 : v8::MaybeLocal<v8::Value> maybe =
1229 7448 : descriptor->Get(context, v8_str(isolate, "value"));
1230 : v8::Local<v8::Value> value;
1231 7568 : if (!maybe.ToLocal(&value)) return;
1232 : v8::Local<v8::String> string;
1233 14896 : if (!value->ToString(context).ToLocal(&string)) return;
1234 :
1235 7448 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1236 7448 : if (string->StringEquals(v8_str(isolate, "i32"))) {
1237 : type = i::wasm::kWasmI32;
1238 4864 : } else if (string->StringEquals(v8_str(isolate, "f32"))) {
1239 : type = i::wasm::kWasmF32;
1240 1928 : } else if (string->StringEquals(v8_str(isolate, "i64"))) {
1241 : type = i::wasm::kWasmI64;
1242 1832 : } else if (string->StringEquals(v8_str(isolate, "f64"))) {
1243 : type = i::wasm::kWasmF64;
1244 824 : } else if (enabled_features.anyref &&
1245 352 : string->StringEquals(v8_str(isolate, "anyref"))) {
1246 : type = i::wasm::kWasmAnyRef;
1247 344 : } else if (enabled_features.anyref &&
1248 112 : string->StringEquals(v8_str(isolate, "anyfunc"))) {
1249 : type = i::wasm::kWasmAnyFunc;
1250 : } else {
1251 : thrower.TypeError(
1252 : "Descriptor property 'value' must be 'i32', 'i64', 'f32', or "
1253 120 : "'f64'");
1254 120 : return;
1255 : }
1256 : }
1257 :
1258 : const uint32_t offset = 0;
1259 : i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
1260 : i::WasmGlobalObject::New(i_isolate, i::MaybeHandle<i::JSArrayBuffer>(),
1261 : i::MaybeHandle<i::FixedArray>(), type, offset,
1262 7328 : is_mutable);
1263 :
1264 : i::Handle<i::WasmGlobalObject> global_obj;
1265 7328 : if (!maybe_global_obj.ToHandle(&global_obj)) {
1266 0 : thrower.RangeError("could not allocate memory");
1267 0 : return;
1268 : }
1269 :
1270 : // Convert value to a WebAssembly value, the default value is 0.
1271 : Local<v8::Value> value = Local<Value>::Cast(args[1]);
1272 7328 : switch (type) {
1273 : case i::wasm::kWasmI32: {
1274 : int32_t i32_value = 0;
1275 2584 : if (!value->IsUndefined()) {
1276 : v8::Local<v8::Int32> int32_value;
1277 4832 : if (!value->ToInt32(context).ToLocal(&int32_value)) return;
1278 4832 : if (!int32_value->Int32Value(context).To(&i32_value)) return;
1279 : }
1280 2584 : global_obj->SetI32(i32_value);
1281 : break;
1282 : }
1283 : case i::wasm::kWasmI64: {
1284 : int64_t i64_value = 0;
1285 96 : if (!value->IsUndefined()) {
1286 48 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1287 48 : if (!enabled_features.bigint) {
1288 16 : thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
1289 16 : return;
1290 : }
1291 :
1292 : v8::Local<v8::BigInt> bigint_value;
1293 64 : if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
1294 24 : i64_value = bigint_value->Int64Value();
1295 : }
1296 72 : global_obj->SetI64(i64_value);
1297 72 : break;
1298 : }
1299 : case i::wasm::kWasmF32: {
1300 : float f32_value = 0;
1301 2936 : if (!value->IsUndefined()) {
1302 : double f64_value = 0;
1303 : v8::Local<v8::Number> number_value;
1304 5600 : if (!value->ToNumber(context).ToLocal(&number_value)) return;
1305 5600 : if (!number_value->NumberValue(context).To(&f64_value)) return;
1306 2800 : f32_value = static_cast<float>(f64_value);
1307 : }
1308 2936 : global_obj->SetF32(f32_value);
1309 2936 : break;
1310 : }
1311 : case i::wasm::kWasmF64: {
1312 : double f64_value = 0;
1313 1360 : if (!value->IsUndefined()) {
1314 : v8::Local<v8::Number> number_value;
1315 2448 : if (!value->ToNumber(context).ToLocal(&number_value)) return;
1316 2448 : if (!number_value->NumberValue(context).To(&f64_value)) return;
1317 : }
1318 1360 : global_obj->SetF64(f64_value);
1319 : break;
1320 : }
1321 : case i::wasm::kWasmAnyRef: {
1322 240 : if (args.Length() < 2) {
1323 : // When no inital value is provided, we have to use the WebAssembly
1324 : // default value 'null', and not the JS default value 'undefined'.
1325 48 : global_obj->SetAnyRef(i_isolate->factory()->null_value());
1326 48 : break;
1327 : }
1328 192 : global_obj->SetAnyRef(Utils::OpenHandle(*value));
1329 192 : break;
1330 : }
1331 : case i::wasm::kWasmAnyFunc: {
1332 112 : if (args.Length() < 2) {
1333 : // When no inital value is provided, we have to use the WebAssembly
1334 : // default value 'null', and not the JS default value 'undefined'.
1335 32 : global_obj->SetAnyFunc(i_isolate, i_isolate->factory()->null_value());
1336 32 : break;
1337 : }
1338 :
1339 80 : if (!global_obj->SetAnyFunc(i_isolate, Utils::OpenHandle(*value))) {
1340 : thrower.TypeError(
1341 : "The value of anyfunc globals must be null or an "
1342 16 : "exported function");
1343 : }
1344 : break;
1345 : }
1346 : default:
1347 0 : UNREACHABLE();
1348 : }
1349 :
1350 : i::Handle<i::JSObject> global_js_object(global_obj);
1351 : args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
1352 : }
1353 :
1354 : // WebAssembly.Exception
1355 8 : void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
1356 : v8::Isolate* isolate = args.GetIsolate();
1357 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1358 16 : HandleScope scope(isolate);
1359 8 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
1360 8 : thrower.TypeError("WebAssembly.Exception cannot be called");
1361 8 : }
1362 :
1363 : constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
1364 : constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
1365 : constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
1366 : constexpr const char* kName_WasmTableObject = "WebAssembly.Table";
1367 :
1368 : #define EXTRACT_THIS(var, WasmType) \
1369 : i::Handle<i::WasmType> var; \
1370 : { \
1371 : i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
1372 : if (!this_arg->Is##WasmType()) { \
1373 : thrower.TypeError("Receiver is not a %s", kName_##WasmType); \
1374 : return; \
1375 : } \
1376 : var = i::Handle<i::WasmType>::cast(this_arg); \
1377 : }
1378 :
1379 43212953 : void WebAssemblyInstanceGetExports(
1380 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1381 : v8::Isolate* isolate = args.GetIsolate();
1382 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1383 86425818 : HandleScope scope(isolate);
1384 43212864 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
1385 43212953 : EXTRACT_THIS(receiver, WasmInstanceObject);
1386 : i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
1387 : args.GetReturnValue().Set(Utils::ToLocal(exports_object));
1388 : }
1389 :
1390 8000 : void WebAssemblyTableGetLength(
1391 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1392 : v8::Isolate* isolate = args.GetIsolate();
1393 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1394 15888 : HandleScope scope(isolate);
1395 7888 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
1396 8000 : EXTRACT_THIS(receiver, WasmTableObject);
1397 7888 : args.GetReturnValue().Set(
1398 : v8::Number::New(isolate, receiver->current_length()));
1399 : }
1400 :
1401 : // WebAssembly.Table.grow(num) -> num
1402 744 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1403 : v8::Isolate* isolate = args.GetIsolate();
1404 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1405 1176 : HandleScope scope(isolate);
1406 432 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
1407 744 : Local<Context> context = isolate->GetCurrentContext();
1408 744 : EXTRACT_THIS(receiver, WasmTableObject);
1409 :
1410 : uint32_t grow_by;
1411 648 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) {
1412 : return;
1413 : }
1414 :
1415 : i::Handle<i::FixedArray> old_array(receiver->elements(), i_isolate);
1416 496 : uint32_t old_size = static_cast<uint32_t>(old_array->length());
1417 :
1418 : uint64_t max_size64 = receiver->maximum_length().IsUndefined(i_isolate)
1419 : ? i::FLAG_wasm_max_table_size
1420 936 : : receiver->maximum_length()->Number();
1421 496 : if (max_size64 > i::FLAG_wasm_max_table_size) {
1422 : max_size64 = i::FLAG_wasm_max_table_size;
1423 : }
1424 :
1425 : DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
1426 :
1427 : uint64_t new_size64 =
1428 496 : static_cast<uint64_t>(old_size) + static_cast<uint64_t>(grow_by);
1429 496 : if (new_size64 > max_size64) {
1430 64 : thrower.RangeError("maximum table size exceeded");
1431 64 : return;
1432 : }
1433 432 : uint32_t new_size = static_cast<uint32_t>(new_size64);
1434 :
1435 432 : if (new_size != old_size) {
1436 400 : receiver->Grow(i_isolate, new_size - old_size);
1437 :
1438 : i::Handle<i::FixedArray> new_array =
1439 400 : i_isolate->factory()->NewFixedArray(new_size);
1440 9597312 : for (uint32_t i = 0; i < old_size; ++i) {
1441 9596912 : new_array->set(i, old_array->get(i));
1442 : }
1443 400 : i::Object null = i::ReadOnlyRoots(i_isolate).null_value();
1444 170590448 : for (uint32_t i = old_size; i < new_size; ++i) new_array->set(i, null);
1445 400 : receiver->set_elements(*new_array);
1446 : }
1447 :
1448 : // TODO(gdeepti): use weak links for instances
1449 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1450 : return_value.Set(old_size);
1451 : }
1452 :
1453 : // WebAssembly.Table.get(num) -> JSFunction
1454 10656 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1455 : v8::Isolate* isolate = args.GetIsolate();
1456 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1457 20296 : HandleScope scope(isolate);
1458 9640 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
1459 10656 : Local<Context> context = isolate->GetCurrentContext();
1460 10656 : EXTRACT_THIS(receiver, WasmTableObject);
1461 :
1462 : uint32_t index;
1463 10560 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
1464 : return;
1465 : }
1466 10088 : if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) {
1467 448 : thrower.RangeError("invalid index %u into function table", index);
1468 448 : return;
1469 : }
1470 :
1471 : i::Handle<i::Object> result =
1472 9640 : i::WasmTableObject::Get(i_isolate, receiver, index);
1473 :
1474 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1475 : return_value.Set(Utils::ToLocal(result));
1476 : }
1477 :
1478 : // WebAssembly.Table.set(num, JSFunction)
1479 4000 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
1480 : v8::Isolate* isolate = args.GetIsolate();
1481 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1482 7088 : HandleScope scope(isolate);
1483 3088 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
1484 4000 : Local<Context> context = isolate->GetCurrentContext();
1485 4000 : EXTRACT_THIS(table_object, WasmTableObject);
1486 :
1487 : // Parameter 0.
1488 : uint32_t index;
1489 3896 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
1490 : return;
1491 : }
1492 3664 : if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) {
1493 328 : thrower.RangeError("invalid index %u into function table", index);
1494 328 : return;
1495 : }
1496 :
1497 3336 : i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
1498 3336 : if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) {
1499 248 : thrower.TypeError("Argument 1 must be null or a WebAssembly function");
1500 248 : return;
1501 : }
1502 3088 : i::WasmTableObject::Set(i_isolate, table_object, index, element);
1503 : }
1504 :
1505 : // WebAssembly.Table.type(WebAssembly.Table) -> TableType
1506 96 : void WebAssemblyTableGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1507 : v8::Isolate* isolate = args.GetIsolate();
1508 160 : HandleScope scope(isolate);
1509 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1510 64 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()");
1511 :
1512 96 : auto maybe_table = GetFirstArgumentAsTable(args, &thrower);
1513 128 : if (thrower.error()) return;
1514 : i::Handle<i::WasmTableObject> table = maybe_table.ToHandleChecked();
1515 64 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1516 :
1517 : Local<String> element;
1518 64 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
1519 64 : if (table->type() == i::wasm::ValueType::kWasmAnyFunc) {
1520 : element = v8_str(isolate, "anyfunc");
1521 16 : } else if (enabled_features.anyref &&
1522 : table->type() == i::wasm::ValueType::kWasmAnyRef) {
1523 : element = v8_str(isolate, "anyref");
1524 : } else {
1525 0 : UNREACHABLE();
1526 : }
1527 : // TODO(aseemgarg): update anyfunc to funcref
1528 192 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1529 128 : v8_str(isolate, "element"), element)
1530 : .IsJust()) {
1531 : return;
1532 : }
1533 :
1534 : uint32_t curr_size = table->current_length();
1535 : DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
1536 192 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1537 : v8_str(isolate, "minimum"),
1538 : v8::Integer::NewFromUnsigned(
1539 192 : isolate, static_cast<uint32_t>(curr_size)))
1540 : .IsJust()) {
1541 : return;
1542 : }
1543 :
1544 64 : if (!table->maximum_length()->IsUndefined()) {
1545 32 : uint64_t max_size = table->maximum_length()->Number();
1546 : DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
1547 96 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1548 : v8_str(isolate, "maximum"),
1549 : v8::Integer::NewFromUnsigned(
1550 96 : isolate, static_cast<uint32_t>(max_size)))
1551 : .IsJust()) {
1552 : return;
1553 : }
1554 : }
1555 :
1556 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1557 : return_value.Set(ret);
1558 : }
1559 :
1560 : // WebAssembly.Memory.grow(num) -> num
1561 724 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
1562 : v8::Isolate* isolate = args.GetIsolate();
1563 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1564 1160 : HandleScope scope(isolate);
1565 436 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
1566 724 : Local<Context> context = isolate->GetCurrentContext();
1567 724 : EXTRACT_THIS(receiver, WasmMemoryObject);
1568 :
1569 : uint32_t delta_size;
1570 636 : if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_size)) {
1571 : return;
1572 : }
1573 :
1574 516 : uint64_t max_size64 = receiver->maximum_pages();
1575 516 : if (max_size64 > uint64_t{i::wasm::max_mem_pages()}) {
1576 168 : max_size64 = i::wasm::max_mem_pages();
1577 : }
1578 : i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);
1579 :
1580 : DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
1581 :
1582 516 : uint64_t old_size64 = old_buffer->byte_length() / i::wasm::kWasmPageSize;
1583 516 : uint64_t new_size64 = old_size64 + static_cast<uint64_t>(delta_size);
1584 :
1585 516 : if (new_size64 > max_size64) {
1586 72 : thrower.RangeError("Maximum memory size exceeded");
1587 72 : return;
1588 : }
1589 :
1590 444 : int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_size);
1591 444 : if (ret == -1) {
1592 8 : thrower.RangeError("Unable to grow instance memory.");
1593 8 : return;
1594 : }
1595 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1596 : return_value.Set(ret);
1597 : }
1598 :
1599 : // WebAssembly.Memory.buffer -> ArrayBuffer
1600 11098634 : void WebAssemblyMemoryGetBuffer(
1601 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1602 : v8::Isolate* isolate = args.GetIsolate();
1603 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1604 22197156 : HandleScope scope(isolate);
1605 11098522 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
1606 11098634 : EXTRACT_THIS(receiver, WasmMemoryObject);
1607 :
1608 : i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
1609 : DCHECK(buffer_obj->IsJSArrayBuffer());
1610 : i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
1611 : i_isolate);
1612 11098522 : if (buffer->is_shared()) {
1613 : // TODO(gdeepti): More needed here for when cached buffer, and current
1614 : // buffer are out of sync, handle that here when bounds checks, and Grow
1615 : // are handled correctly.
1616 : Maybe<bool> result =
1617 11096258 : buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
1618 11096258 : if (!result.FromJust()) {
1619 : thrower.TypeError(
1620 0 : "Status of setting SetIntegrityLevel of buffer is false.");
1621 : }
1622 : }
1623 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1624 : return_value.Set(Utils::ToLocal(buffer));
1625 : }
1626 :
1627 : // WebAssembly.Memory.type(WebAssembly.Memory) -> MemoryType
1628 80 : void WebAssemblyMemoryGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1629 : v8::Isolate* isolate = args.GetIsolate();
1630 128 : HandleScope scope(isolate);
1631 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1632 48 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()");
1633 :
1634 80 : auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
1635 112 : if (thrower.error()) return;
1636 : i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
1637 48 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1638 : i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
1639 :
1640 48 : size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
1641 : DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
1642 144 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1643 : v8_str(isolate, "minimum"),
1644 : v8::Integer::NewFromUnsigned(
1645 144 : isolate, static_cast<uint32_t>(curr_size)))
1646 : .IsJust()) {
1647 : return;
1648 : }
1649 :
1650 48 : if (memory->has_maximum_pages()) {
1651 24 : uint64_t max_size = memory->maximum_pages();
1652 : DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
1653 72 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1654 : v8_str(isolate, "maximum"),
1655 : v8::Integer::NewFromUnsigned(
1656 72 : isolate, static_cast<uint32_t>(max_size)))
1657 : .IsJust()) {
1658 : return;
1659 : }
1660 : }
1661 :
1662 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1663 : return_value.Set(ret);
1664 : }
1665 :
1666 9624 : void WebAssemblyGlobalGetValueCommon(
1667 : const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
1668 : v8::Isolate* isolate = args.GetIsolate();
1669 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1670 19088 : HandleScope scope(isolate);
1671 9464 : ScheduledErrorThrower thrower(i_isolate, name);
1672 9624 : EXTRACT_THIS(receiver, WasmGlobalObject);
1673 :
1674 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1675 :
1676 9464 : switch (receiver->type()) {
1677 : case i::wasm::kWasmI32:
1678 : return_value.Set(receiver->GetI32());
1679 : break;
1680 : case i::wasm::kWasmI64: {
1681 112 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1682 112 : if (enabled_features.bigint) {
1683 72 : Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
1684 :
1685 : return_value.Set(value);
1686 : } else {
1687 40 : thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
1688 : }
1689 : break;
1690 : }
1691 : case i::wasm::kWasmF32:
1692 3288 : return_value.Set(receiver->GetF32());
1693 : break;
1694 : case i::wasm::kWasmF64:
1695 : return_value.Set(receiver->GetF64());
1696 : break;
1697 : case i::wasm::kWasmAnyRef:
1698 : case i::wasm::kWasmAnyFunc:
1699 : case i::wasm::kWasmExceptRef:
1700 1664 : return_value.Set(Utils::ToLocal(receiver->GetRef()));
1701 : break;
1702 : default:
1703 0 : UNREACHABLE();
1704 : }
1705 : }
1706 :
1707 : // WebAssembly.Global.valueOf() -> num
1708 3360 : void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
1709 3360 : return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
1710 : }
1711 :
1712 : // get WebAssembly.Global.value -> num
1713 6264 : void WebAssemblyGlobalGetValue(
1714 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1715 6264 : return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
1716 : }
1717 :
1718 : // set WebAssembly.Global.value(num)
1719 2944 : void WebAssemblyGlobalSetValue(
1720 : const v8::FunctionCallbackInfo<v8::Value>& args) {
1721 : v8::Isolate* isolate = args.GetIsolate();
1722 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1723 5568 : HandleScope scope(isolate);
1724 2944 : Local<Context> context = isolate->GetCurrentContext();
1725 2624 : ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
1726 2944 : EXTRACT_THIS(receiver, WasmGlobalObject);
1727 :
1728 2872 : if (!receiver->is_mutable()) {
1729 216 : thrower.TypeError("Can't set the value of an immutable global.");
1730 216 : return;
1731 : }
1732 2656 : if (args[0]->IsUndefined()) {
1733 24 : thrower.TypeError("Argument 0 is required");
1734 24 : return;
1735 : }
1736 :
1737 2632 : switch (receiver->type()) {
1738 : case i::wasm::kWasmI32: {
1739 : int32_t i32_value = 0;
1740 2000 : if (!args[0]->Int32Value(context).To(&i32_value)) return;
1741 1000 : receiver->SetI32(i32_value);
1742 : break;
1743 : }
1744 : case i::wasm::kWasmI64: {
1745 32 : auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
1746 32 : if (enabled_features.bigint) {
1747 : v8::Local<v8::BigInt> bigint_value;
1748 48 : if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
1749 32 : receiver->SetI64(bigint_value->Int64Value());
1750 : } else {
1751 8 : thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
1752 : }
1753 24 : break;
1754 : }
1755 : case i::wasm::kWasmF32: {
1756 : double f64_value = 0;
1757 1936 : if (!args[0]->NumberValue(context).To(&f64_value)) return;
1758 1936 : receiver->SetF32(static_cast<float>(f64_value));
1759 : break;
1760 : }
1761 : case i::wasm::kWasmF64: {
1762 : double f64_value = 0;
1763 880 : if (!args[0]->NumberValue(context).To(&f64_value)) return;
1764 440 : receiver->SetF64(f64_value);
1765 : break;
1766 : }
1767 : case i::wasm::kWasmAnyRef:
1768 : case i::wasm::kWasmExceptRef: {
1769 144 : receiver->SetAnyRef(Utils::OpenHandle(*args[0]));
1770 144 : break;
1771 : }
1772 : case i::wasm::kWasmAnyFunc: {
1773 48 : if (!receiver->SetAnyFunc(i_isolate, Utils::OpenHandle(*args[0]))) {
1774 : thrower.TypeError(
1775 : "value of an anyfunc reference must be either null or an "
1776 16 : "exported function");
1777 : }
1778 : break;
1779 : }
1780 : default:
1781 0 : UNREACHABLE();
1782 : }
1783 : }
1784 :
1785 : // WebAssembly.Global.type(WebAssembly.Global) -> GlobalType
1786 88 : void WebAssemblyGlobalGetType(const v8::FunctionCallbackInfo<v8::Value>& args) {
1787 : v8::Isolate* isolate = args.GetIsolate();
1788 144 : HandleScope scope(isolate);
1789 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1790 56 : ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()");
1791 :
1792 88 : auto maybe_global = GetFirstArgumentAsGlobal(args, &thrower);
1793 120 : if (thrower.error()) return;
1794 : i::Handle<i::WasmGlobalObject> global = maybe_global.ToHandleChecked();
1795 56 : v8::Local<v8::Object> ret = v8::Object::New(isolate);
1796 :
1797 168 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1798 : v8_str(isolate, "mutable"),
1799 112 : v8::Boolean::New(isolate, global->is_mutable()))
1800 : .IsJust()) {
1801 : return;
1802 : }
1803 :
1804 : Local<String> type;
1805 56 : switch (global->type()) {
1806 : case i::wasm::kWasmI32: {
1807 : type = v8_str(isolate, "i32");
1808 16 : break;
1809 : }
1810 : case i::wasm::kWasmI64: {
1811 : type = v8_str(isolate, "i64");
1812 8 : break;
1813 : }
1814 : case i::wasm::kWasmF32: {
1815 : type = v8_str(isolate, "f32");
1816 8 : break;
1817 : }
1818 : case i::wasm::kWasmF64: {
1819 : type = v8_str(isolate, "f64");
1820 8 : break;
1821 : }
1822 : case i::wasm::kWasmAnyRef: {
1823 : type = v8_str(isolate, "anyref");
1824 16 : break;
1825 : }
1826 : default:
1827 0 : UNREACHABLE();
1828 : }
1829 168 : if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
1830 112 : v8_str(isolate, "value"), type)
1831 : .IsJust()) {
1832 : return;
1833 : }
1834 :
1835 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
1836 : return_value.Set(ret);
1837 : }
1838 :
1839 : } // namespace
1840 :
1841 : // TODO(titzer): we use the API to create the function template because the
1842 : // internal guts are too ugly to replicate here.
1843 1716652 : static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
1844 : i::Isolate* i_isolate, FunctionCallback func) {
1845 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1846 1716652 : Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
1847 1716656 : templ->ReadOnlyPrototype();
1848 1716655 : return v8::Utils::OpenHandle(*templ);
1849 : }
1850 :
1851 : static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
1852 : i::Isolate* i_isolate) {
1853 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
1854 408866 : Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
1855 : return v8::Utils::OpenHandle(*templ);
1856 : }
1857 :
1858 : namespace internal {
1859 :
1860 1716654 : Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
1861 : FunctionCallback func) {
1862 1716654 : Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
1863 : Handle<JSFunction> function =
1864 3433296 : ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
1865 : DCHECK(function->shared()->HasSharedName());
1866 1716644 : return function;
1867 : }
1868 :
1869 1308045 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
1870 : const char* str, FunctionCallback func,
1871 : int length = 0,
1872 : PropertyAttributes attributes = NONE) {
1873 : Handle<String> name = v8_str(isolate, str);
1874 1308041 : Handle<JSFunction> function = CreateFunc(isolate, name, func);
1875 : function->shared()->set_length(length);
1876 1308041 : JSObject::AddProperty(isolate, object, name, function, attributes);
1877 1308043 : return function;
1878 : }
1879 :
1880 0 : Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
1881 : Handle<JSObject> object,
1882 : const char* str,
1883 : FunctionCallback func) {
1884 408862 : return InstallFunc(isolate, object, str, func, 1, DONT_ENUM);
1885 : }
1886 :
1887 326888 : Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
1888 653778 : return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
1889 326890 : .ToHandleChecked();
1890 : }
1891 :
1892 245167 : void InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str,
1893 : FunctionCallback func) {
1894 : Handle<String> name = v8_str(isolate, str);
1895 : Handle<JSFunction> function =
1896 245167 : CreateFunc(isolate, GetterName(isolate, name), func);
1897 :
1898 245167 : Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
1899 : Utils::ToLocal(function),
1900 245167 : Local<Function>(), v8::None);
1901 245167 : }
1902 :
1903 81722 : Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
1904 163445 : return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
1905 81723 : .ToHandleChecked();
1906 : }
1907 :
1908 81722 : void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
1909 : const char* str, FunctionCallback getter,
1910 : FunctionCallback setter) {
1911 : Handle<String> name = v8_str(isolate, str);
1912 : Handle<JSFunction> getter_func =
1913 81722 : CreateFunc(isolate, GetterName(isolate, name), getter);
1914 : Handle<JSFunction> setter_func =
1915 81723 : CreateFunc(isolate, SetterName(isolate, name), setter);
1916 : setter_func->shared()->set_length(1);
1917 :
1918 : v8::PropertyAttribute attributes = v8::None;
1919 :
1920 81722 : Utils::ToLocal(object)->SetAccessorProperty(
1921 : Utils::ToLocal(name), Utils::ToLocal(getter_func),
1922 81723 : Utils::ToLocal(setter_func), attributes);
1923 81722 : }
1924 :
1925 : // Assigns a dummy instance template to the given constructor function. Used to
1926 : // make sure the implicit receivers for the constructors in this file have an
1927 : // instance type different from the internal one, they allocate the resulting
1928 : // object explicitly and ignore implicit receiver.
1929 408866 : void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
1930 : Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
1931 408865 : FunctionTemplateInfo::SetInstanceTemplate(
1932 : isolate, handle(fun->shared()->get_api_func_data(), isolate),
1933 408867 : instance_template);
1934 408865 : }
1935 :
1936 : // static
1937 1176301 : void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
1938 1176301 : Handle<JSGlobalObject> global = isolate->global_object();
1939 : Handle<Context> context(global->native_context(), isolate);
1940 : // Install the JS API once only.
1941 : Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
1942 1176301 : if (!prev->IsUndefined(isolate)) {
1943 : DCHECK(prev->IsJSFunction());
1944 1094578 : return;
1945 : }
1946 :
1947 : Factory* factory = isolate->factory();
1948 :
1949 : // Setup WebAssembly
1950 : Handle<String> name = v8_str(isolate, "WebAssembly");
1951 : NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
1952 81723 : name, isolate->strict_function_map(), LanguageMode::kStrict);
1953 81723 : Handle<JSFunction> cons = factory->NewFunction(args);
1954 163446 : JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
1955 : Handle<JSObject> webassembly =
1956 81723 : factory->NewJSObject(cons, AllocationType::kOld);
1957 :
1958 : PropertyAttributes ro_attributes =
1959 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
1960 81723 : JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
1961 81723 : name, ro_attributes);
1962 81723 : InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
1963 81721 : InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
1964 81723 : InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
1965 :
1966 81723 : if (FLAG_wasm_test_streaming) {
1967 : isolate->set_wasm_streaming_callback(WasmStreamingCallbackForTesting);
1968 : }
1969 :
1970 81723 : if (isolate->wasm_streaming_callback() != nullptr) {
1971 : InstallFunc(isolate, webassembly, "compileStreaming",
1972 96 : WebAssemblyCompileStreaming, 1);
1973 : InstallFunc(isolate, webassembly, "instantiateStreaming",
1974 96 : WebAssemblyInstantiateStreaming, 1);
1975 : }
1976 :
1977 : // Expose the API on the global object if configured to do so.
1978 81723 : if (exposed_on_global_object) {
1979 81698 : JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM);
1980 : }
1981 :
1982 : // Setup Module
1983 : Handle<JSFunction> module_constructor =
1984 : InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule);
1985 81723 : context->set_wasm_module_constructor(*module_constructor);
1986 81723 : SetDummyInstanceTemplate(isolate, module_constructor);
1987 81723 : JSFunction::EnsureHasInitialMap(module_constructor);
1988 : Handle<JSObject> module_proto(
1989 163445 : JSObject::cast(module_constructor->instance_prototype()), isolate);
1990 : i::Handle<i::Map> module_map =
1991 81722 : isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
1992 81723 : JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
1993 : InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
1994 81722 : 1);
1995 : InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
1996 81722 : 1);
1997 : InstallFunc(isolate, module_constructor, "customSections",
1998 81721 : WebAssemblyModuleCustomSections, 2);
1999 81721 : JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
2000 81722 : v8_str(isolate, "WebAssembly.Module"), ro_attributes);
2001 :
2002 : // Setup Instance
2003 : Handle<JSFunction> instance_constructor = InstallConstructorFunc(
2004 : isolate, webassembly, "Instance", WebAssemblyInstance);
2005 81723 : context->set_wasm_instance_constructor(*instance_constructor);
2006 81722 : SetDummyInstanceTemplate(isolate, instance_constructor);
2007 81722 : JSFunction::EnsureHasInitialMap(instance_constructor);
2008 : Handle<JSObject> instance_proto(
2009 163444 : JSObject::cast(instance_constructor->instance_prototype()), isolate);
2010 : i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
2011 81722 : i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
2012 81722 : JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
2013 : InstallGetter(isolate, instance_proto, "exports",
2014 81722 : WebAssemblyInstanceGetExports);
2015 81722 : JSObject::AddProperty(isolate, instance_proto,
2016 : factory->to_string_tag_symbol(),
2017 81722 : v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
2018 :
2019 : // The context is not set up completely yet. That's why we cannot use
2020 : // {WasmFeaturesFromIsolate} and have to use {WasmFeaturesFromFlags} instead.
2021 81722 : auto enabled_features = i::wasm::WasmFeaturesFromFlags();
2022 :
2023 : // Setup Table
2024 : Handle<JSFunction> table_constructor =
2025 : InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable);
2026 81723 : context->set_wasm_table_constructor(*table_constructor);
2027 81723 : SetDummyInstanceTemplate(isolate, table_constructor);
2028 81723 : JSFunction::EnsureHasInitialMap(table_constructor);
2029 : Handle<JSObject> table_proto(
2030 163445 : JSObject::cast(table_constructor->instance_prototype()), isolate);
2031 : i::Handle<i::Map> table_map =
2032 81722 : isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
2033 81723 : JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
2034 81723 : InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
2035 81722 : InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
2036 81721 : InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
2037 81722 : InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
2038 81720 : if (enabled_features.type_reflection) {
2039 16 : InstallFunc(isolate, table_constructor, "type", WebAssemblyTableGetType, 1);
2040 : }
2041 81721 : JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
2042 81722 : v8_str(isolate, "WebAssembly.Table"), ro_attributes);
2043 :
2044 : // Setup Memory
2045 : Handle<JSFunction> memory_constructor =
2046 : InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory);
2047 81723 : context->set_wasm_memory_constructor(*memory_constructor);
2048 81723 : SetDummyInstanceTemplate(isolate, memory_constructor);
2049 81723 : JSFunction::EnsureHasInitialMap(memory_constructor);
2050 : Handle<JSObject> memory_proto(
2051 163446 : JSObject::cast(memory_constructor->instance_prototype()), isolate);
2052 : i::Handle<i::Map> memory_map =
2053 81723 : isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
2054 81723 : JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
2055 81723 : InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
2056 81723 : InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
2057 81723 : if (enabled_features.type_reflection) {
2058 : InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryGetType,
2059 16 : 1);
2060 : }
2061 81723 : JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
2062 81723 : v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
2063 :
2064 : // Setup Global
2065 : Handle<JSFunction> global_constructor =
2066 : InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal);
2067 81723 : context->set_wasm_global_constructor(*global_constructor);
2068 81723 : SetDummyInstanceTemplate(isolate, global_constructor);
2069 81723 : JSFunction::EnsureHasInitialMap(global_constructor);
2070 : Handle<JSObject> global_proto(
2071 163446 : JSObject::cast(global_constructor->instance_prototype()), isolate);
2072 : i::Handle<i::Map> global_map =
2073 81723 : isolate->factory()->NewMap(i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
2074 81723 : JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
2075 81723 : InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
2076 : InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
2077 81722 : WebAssemblyGlobalSetValue);
2078 81722 : if (enabled_features.type_reflection) {
2079 : InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalGetType,
2080 16 : 1);
2081 : }
2082 81723 : JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
2083 81723 : v8_str(isolate, "WebAssembly.Global"), ro_attributes);
2084 :
2085 : // Setup Exception
2086 81723 : if (enabled_features.eh) {
2087 : Handle<JSFunction> exception_constructor = InstallConstructorFunc(
2088 : isolate, webassembly, "Exception", WebAssemblyException);
2089 252 : context->set_wasm_exception_constructor(*exception_constructor);
2090 252 : SetDummyInstanceTemplate(isolate, exception_constructor);
2091 252 : JSFunction::EnsureHasInitialMap(exception_constructor);
2092 : Handle<JSObject> exception_proto(
2093 504 : JSObject::cast(exception_constructor->instance_prototype()), isolate);
2094 : i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
2095 252 : i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
2096 252 : JSFunction::SetInitialMap(exception_constructor, exception_map,
2097 252 : exception_proto);
2098 : }
2099 :
2100 : // Setup errors
2101 : Handle<JSFunction> compile_error(
2102 245169 : isolate->native_context()->wasm_compile_error_function(), isolate);
2103 81722 : JSObject::AddProperty(isolate, webassembly,
2104 : isolate->factory()->CompileError_string(),
2105 81723 : compile_error, DONT_ENUM);
2106 : Handle<JSFunction> link_error(
2107 245166 : isolate->native_context()->wasm_link_error_function(), isolate);
2108 81723 : JSObject::AddProperty(isolate, webassembly,
2109 : isolate->factory()->LinkError_string(), link_error,
2110 81722 : DONT_ENUM);
2111 : Handle<JSFunction> runtime_error(
2112 245169 : isolate->native_context()->wasm_runtime_error_function(), isolate);
2113 81723 : JSObject::AddProperty(isolate, webassembly,
2114 : isolate->factory()->RuntimeError_string(),
2115 81723 : runtime_error, DONT_ENUM);
2116 : }
2117 :
2118 : #undef ASSIGN
2119 : #undef EXTRACT_THIS
2120 :
2121 : } // namespace internal
2122 122004 : } // namespace v8
|