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/api-natives.h"
6 : #include "src/api.h"
7 : #include "src/asmjs/asm-js.h"
8 : #include "src/asmjs/asm-typer.h"
9 : #include "src/asmjs/asm-wasm-builder.h"
10 : #include "src/assert-scope.h"
11 : #include "src/ast/ast.h"
12 : #include "src/execution.h"
13 : #include "src/factory.h"
14 : #include "src/handles.h"
15 : #include "src/isolate.h"
16 : #include "src/objects-inl.h"
17 : #include "src/objects.h"
18 : #include "src/parsing/parse-info.h"
19 :
20 : #include "src/wasm/module-decoder.h"
21 : #include "src/wasm/wasm-js.h"
22 : #include "src/wasm/wasm-limits.h"
23 : #include "src/wasm/wasm-module.h"
24 : #include "src/wasm/wasm-objects.h"
25 : #include "src/wasm/wasm-result.h"
26 :
27 : typedef uint8_t byte;
28 :
29 : using v8::internal::wasm::ErrorThrower;
30 :
31 : namespace v8 {
32 :
33 : namespace {
34 :
35 : #define ASSIGN(type, var, expr) \
36 : Local<type> var; \
37 : do { \
38 : if (!expr.ToLocal(&var)) { \
39 : DCHECK(i_isolate->has_scheduled_exception()); \
40 : return; \
41 : } else { \
42 : DCHECK(!i_isolate->has_scheduled_exception()); \
43 : } \
44 : } while (false)
45 :
46 : // TODO(wasm): move brand check to the respective types, and don't throw
47 : // in it, rather, use a provided ErrorThrower, or let caller handle it.
48 68041 : static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) {
49 68041 : if (!value->IsJSObject()) return false;
50 : i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value);
51 67816 : Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym);
52 : return has_brand.FromMaybe(false);
53 : }
54 :
55 65401 : static bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym,
56 : ErrorThrower* thrower, const char* msg) {
57 65401 : return HasBrand(value, sym) ? true : (thrower->TypeError("%s", msg), false);
58 : }
59 :
60 : i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
61 2324645 : return isolate->factory()->NewStringFromAsciiChecked(str);
62 : }
63 : Local<String> v8_str(Isolate* isolate, const char* str) {
64 : return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
65 : }
66 :
67 40777 : i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule(
68 81554 : const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
69 : v8::Isolate* isolate = args.GetIsolate();
70 40777 : if (args.Length() < 1) {
71 120 : thrower->TypeError("Argument 0 must be a WebAssembly.Module");
72 : return {};
73 : }
74 :
75 40657 : Local<Context> context = isolate->GetCurrentContext();
76 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
77 40657 : if (!BrandCheck(Utils::OpenHandle(*args[0]),
78 : i::handle(i_context->wasm_module_sym()), thrower,
79 40657 : "Argument 0 must be a WebAssembly.Module")) {
80 : return {};
81 : }
82 :
83 : Local<Object> module_obj = Local<Object>::Cast(args[0]);
84 : return i::Handle<i::WasmModuleObject>::cast(
85 : v8::Utils::OpenHandle(*module_obj));
86 : }
87 :
88 13661 : i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
89 13661 : const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
90 13661 : if (args.Length() < 1) {
91 135 : thrower->TypeError("Argument 0 must be a buffer source");
92 135 : return i::wasm::ModuleWireBytes(nullptr, nullptr);
93 : }
94 :
95 : const byte* start = nullptr;
96 : size_t length = 0;
97 : v8::Local<v8::Value> source = args[0];
98 13526 : if (source->IsArrayBuffer()) {
99 : // A raw array buffer was passed.
100 : Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
101 12116 : ArrayBuffer::Contents contents = buffer->GetContents();
102 :
103 12116 : start = reinterpret_cast<const byte*>(contents.Data());
104 12116 : length = contents.ByteLength();
105 1410 : } else if (source->IsTypedArray()) {
106 : // A TypedArray was passed.
107 : Local<TypedArray> array = Local<TypedArray>::Cast(source);
108 1050 : Local<ArrayBuffer> buffer = array->Buffer();
109 :
110 1050 : ArrayBuffer::Contents contents = buffer->GetContents();
111 :
112 : start =
113 1050 : reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset();
114 1050 : length = array->ByteLength();
115 : } else {
116 360 : thrower->TypeError("Argument 0 must be a buffer source");
117 : }
118 : DCHECK_IMPLIES(length, start != nullptr);
119 13526 : if (length == 0) {
120 765 : thrower->CompileError("BufferSource argument is empty");
121 : }
122 13526 : if (length > i::wasm::kV8MaxWasmModuleSize) {
123 : thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
124 15 : i::wasm::kV8MaxWasmModuleSize, length);
125 : }
126 13526 : if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
127 : // TODO(titzer): use the handle as well?
128 25492 : return i::wasm::ModuleWireBytes(start, start + length);
129 : }
130 :
131 40777 : i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
132 : ErrorThrower* thrower) {
133 40777 : if (arg->IsUndefined()) return {};
134 :
135 37037 : if (!arg->IsObject()) {
136 225 : thrower->TypeError("Argument 1 must be an object");
137 : return {};
138 : }
139 : Local<Object> obj = Local<Object>::Cast(arg);
140 : return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
141 : }
142 :
143 : // WebAssembly.compile(bytes) -> Promise
144 2460 : void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
145 : v8::Isolate* isolate = args.GetIsolate();
146 1245 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
147 1245 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
148 1725 : if (i_isolate->wasm_compile_callback()(args)) return;
149 :
150 1980 : HandleScope scope(isolate);
151 765 : ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
152 :
153 1215 : Local<Context> context = isolate->GetCurrentContext();
154 2880 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
155 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
156 1215 : return_value.Set(resolver->GetPromise());
157 :
158 1215 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
159 1215 : if (thrower.error()) {
160 450 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
161 450 : CHECK_IMPLIES(!maybe.FromMaybe(false),
162 : i_isolate->has_scheduled_exception());
163 : return;
164 : }
165 1530 : i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise());
166 1530 : i::wasm::AsyncCompile(i_isolate, promise, bytes);
167 : }
168 :
169 : // WebAssembly.validate(bytes) -> bool
170 2400 : void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
171 : v8::Isolate* isolate = args.GetIsolate();
172 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
173 1200 : HandleScope scope(isolate);
174 1200 : ErrorThrower thrower(i_isolate, "WebAssembly.validate()");
175 :
176 1200 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
177 :
178 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
179 2310 : if (!thrower.error() &&
180 : i::wasm::SyncValidate(reinterpret_cast<i::Isolate*>(isolate), &thrower,
181 1110 : bytes)) {
182 : return_value.Set(v8::True(isolate));
183 : } else {
184 615 : if (thrower.wasm_error()) thrower.Reify(); // Clear error.
185 : return_value.Set(v8::False(isolate));
186 1200 : }
187 1200 : }
188 :
189 : // new WebAssembly.Module(bytes) -> WebAssembly.Module
190 21592 : void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
191 : v8::Isolate* isolate = args.GetIsolate();
192 11276 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
193 12236 : if (i_isolate->wasm_module_callback()(args)) return;
194 :
195 11246 : HandleScope scope(isolate);
196 10316 : ErrorThrower thrower(i_isolate, "WebAssembly.Module()");
197 :
198 11246 : auto bytes = GetFirstArgumentAsBytes(args, &thrower);
199 :
200 11246 : if (thrower.error()) {
201 930 : return;
202 : }
203 : i::MaybeHandle<i::Object> module_obj =
204 21742 : i::wasm::SyncCompile(i_isolate, &thrower, bytes);
205 10871 : if (module_obj.is_null()) return;
206 :
207 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
208 10316 : return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
209 : }
210 :
211 : // WebAssembly.Module.imports(module) -> Array<Import>
212 360 : void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
213 150 : HandleScope scope(args.GetIsolate());
214 : v8::Isolate* isolate = args.GetIsolate();
215 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
216 60 : ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");
217 :
218 150 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
219 300 : if (thrower.error()) return;
220 60 : auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
221 60 : args.GetReturnValue().Set(Utils::ToLocal(imports));
222 : }
223 :
224 : // WebAssembly.Module.exports(module) -> Array<Export>
225 360 : void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
226 150 : HandleScope scope(args.GetIsolate());
227 : v8::Isolate* isolate = args.GetIsolate();
228 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
229 60 : ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
230 :
231 150 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
232 300 : if (thrower.error()) return;
233 60 : auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
234 60 : args.GetReturnValue().Set(Utils::ToLocal(exports));
235 : }
236 :
237 : // WebAssembly.Module.customSections(module, name) -> Array<Section>
238 210 : void WebAssemblyModuleCustomSections(
239 585 : const v8::FunctionCallbackInfo<v8::Value>& args) {
240 210 : HandleScope scope(args.GetIsolate());
241 : v8::Isolate* isolate = args.GetIsolate();
242 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
243 60 : ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()");
244 :
245 210 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
246 210 : if (thrower.error()) return;
247 :
248 105 : if (args.Length() < 2) {
249 30 : thrower.TypeError("Argument 1 must be a string");
250 30 : return;
251 : }
252 :
253 : i::Handle<i::Object> name = Utils::OpenHandle(*args[1]);
254 75 : if (!name->IsString()) {
255 15 : thrower.TypeError("Argument 1 must be a string");
256 15 : return;
257 : }
258 :
259 : auto custom_sections =
260 : i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
261 60 : i::Handle<i::String>::cast(name), &thrower);
262 60 : if (thrower.error()) return;
263 60 : args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
264 : }
265 :
266 40777 : MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
267 : Local<Value> module,
268 : Local<Value> ffi) {
269 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
270 :
271 : ErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
272 : i::MaybeHandle<i::JSReceiver> maybe_imports =
273 40777 : GetValueAsImports(ffi, &thrower);
274 40777 : if (thrower.error()) return {};
275 :
276 : i::Handle<i::WasmModuleObject> module_obj =
277 : i::Handle<i::WasmModuleObject>::cast(
278 40552 : Utils::OpenHandle(Object::Cast(*module)));
279 : i::MaybeHandle<i::Object> instance_object =
280 : i::wasm::SyncInstantiate(i_isolate, &thrower, module_obj, maybe_imports,
281 81104 : i::MaybeHandle<i::JSArrayBuffer>());
282 :
283 40552 : if (instance_object.is_null()) {
284 : // TODO(wasm): this *should* mean there's an error to throw, but
285 : // we exit sometimes the instantiation pipeline without throwing.
286 : // v8:6232.
287 825 : return {};
288 : }
289 39727 : return Utils::ToLocal(instance_object.ToHandleChecked());
290 : }
291 :
292 : // Entered as internal implementation detail of sync and async instantiate.
293 : // args[0] *must* be a WebAssembly.Module.
294 165 : void WebAssemblyInstantiateImplCallback(
295 570 : const v8::FunctionCallbackInfo<v8::Value>& args) {
296 : DCHECK_GE(args.Length(), 1);
297 : v8::Isolate* isolate = args.GetIsolate();
298 : MicrotasksScope does_not_run_microtasks(isolate,
299 165 : MicrotasksScope::kDoNotRunMicrotasks);
300 :
301 330 : HandleScope scope(args.GetIsolate());
302 165 : Local<Value> module = args[0];
303 165 : Local<Value> ffi = args.Data();
304 : Local<Value> instance;
305 330 : if (WebAssemblyInstantiateImpl(isolate, module, ffi).ToLocal(&instance)) {
306 : args.GetReturnValue().Set(instance);
307 165 : }
308 165 : }
309 :
310 510 : void WebAssemblyInstantiateToPairCallback(
311 1725 : const v8::FunctionCallbackInfo<v8::Value>& args) {
312 : DCHECK_GE(args.Length(), 1);
313 : Isolate* isolate = args.GetIsolate();
314 : MicrotasksScope does_not_run_microtasks(isolate,
315 510 : MicrotasksScope::kDoNotRunMicrotasks);
316 :
317 705 : HandleScope scope(args.GetIsolate());
318 :
319 510 : Local<Context> context = isolate->GetCurrentContext();
320 510 : Local<Value> module = args[0];
321 :
322 : const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
323 : const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
324 : Local<Value> instance;
325 510 : if (!WebAssemblyInstantiateImpl(isolate, module, args.Data())
326 1020 : .ToLocal(&instance)) {
327 315 : return;
328 : }
329 :
330 195 : Local<Object> ret = Object::New(isolate);
331 : Local<String> instance_name =
332 : String::NewFromOneByte(isolate, instance_str,
333 : NewStringType::kInternalized)
334 195 : .ToLocalChecked();
335 : Local<String> module_name =
336 : String::NewFromOneByte(isolate, module_str, NewStringType::kInternalized)
337 195 : .ToLocalChecked();
338 :
339 195 : CHECK(ret->CreateDataProperty(context, instance_name, instance).IsJust());
340 195 : CHECK(ret->CreateDataProperty(context, module_name, module).IsJust());
341 195 : args.GetReturnValue().Set(ret);
342 : }
343 :
344 : // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
345 120051 : void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
346 : Isolate* isolate = args.GetIsolate();
347 : MicrotasksScope does_not_run_microtasks(isolate,
348 40297 : MicrotasksScope::kDoNotRunMicrotasks);
349 :
350 80399 : HandleScope scope(args.GetIsolate());
351 40297 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
352 40492 : if (i_isolate->wasm_instance_callback()(args)) return;
353 :
354 40102 : ErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
355 :
356 40267 : auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
357 40267 : if (thrower.error()) return;
358 :
359 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
360 : // We'll check for that in WebAssemblyInstantiateImpl.
361 40102 : Local<Value> data = args[1];
362 :
363 : Local<Value> instance;
364 80204 : if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
365 : args.GetReturnValue().Set(instance);
366 40102 : }
367 : }
368 :
369 : // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
370 : // WebAssembly.instantiate(bytes, imports) ->
371 : // {module: WebAssembly.Module, instance: WebAssembly.Instance}
372 35070 : void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
373 : v8::Isolate* isolate = args.GetIsolate();
374 11205 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
375 11205 : MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
376 21570 : if (i_isolate->wasm_instantiate_callback()(args)) return;
377 :
378 840 : ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
379 :
380 12030 : HandleScope scope(isolate);
381 :
382 11190 : Local<Context> context = isolate->GetCurrentContext();
383 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
384 :
385 32730 : ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
386 11175 : Local<Promise> module_promise = resolver->GetPromise();
387 : args.GetReturnValue().Set(module_promise);
388 :
389 11175 : if (args.Length() < 1) {
390 : thrower.TypeError(
391 : "Argument 0 must be provided and must be either a buffer source or a "
392 10275 : "WebAssembly.Module object");
393 10275 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
394 10275 : CHECK_IMPLIES(!maybe.FromMaybe(false),
395 : i_isolate->has_scheduled_exception());
396 : return;
397 : }
398 :
399 900 : Local<Value> first_arg_value = args[0];
400 : i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
401 900 : if (!first_arg->IsJSObject()) {
402 : thrower.TypeError(
403 60 : "Argument 0 must be a buffer source or a WebAssembly.Module object");
404 60 : auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
405 60 : CHECK_IMPLIES(!maybe.FromMaybe(false),
406 : i_isolate->has_scheduled_exception());
407 : return;
408 : }
409 :
410 : FunctionCallback instantiator = nullptr;
411 840 : if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) {
412 165 : module_promise = resolver->GetPromise();
413 165 : if (!resolver->Resolve(context, first_arg_value).IsJust()) return;
414 : instantiator = WebAssemblyInstantiateImplCallback;
415 : } else {
416 1350 : ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
417 1350 : ASSIGN(Value, async_compile_retval,
418 : async_compile->Call(context, args.Holder(), 1, &first_arg_value));
419 : module_promise = Local<Promise>::Cast(async_compile_retval);
420 : instantiator = WebAssemblyInstantiateToPairCallback;
421 : }
422 : DCHECK(!module_promise.IsEmpty());
423 : DCHECK_NOT_NULL(instantiator);
424 : // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
425 : // We'll check for that in WebAssemblyInstantiateImpl.
426 840 : Local<Value> data = args[1];
427 1680 : ASSIGN(Function, instantiate_impl,
428 : Function::New(context, instantiator, data));
429 1680 : ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
430 840 : args.GetReturnValue().Set(result);
431 : }
432 :
433 2940 : bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
434 : Local<Context> context, Local<v8::Object> object,
435 : Local<String> property, int* result,
436 : int64_t lower_bound, uint64_t upper_bound) {
437 2940 : v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
438 : v8::Local<v8::Value> value;
439 2940 : if (maybe.ToLocal(&value)) {
440 : int64_t number;
441 5880 : if (!value->IntegerValue(context).To(&number)) return false;
442 2880 : if (number < lower_bound) {
443 : thrower->RangeError("Property value %" PRId64
444 : " is below the lower bound %" PRIx64,
445 240 : number, lower_bound);
446 : return false;
447 : }
448 2640 : if (number > static_cast<int64_t>(upper_bound)) {
449 : thrower->RangeError("Property value %" PRId64
450 : " is above the upper bound %" PRIu64,
451 195 : number, upper_bound);
452 : return false;
453 : }
454 2445 : *result = static_cast<int>(number);
455 : return true;
456 : }
457 : return false;
458 : }
459 :
460 : // new WebAssembly.Table(args) -> WebAssembly.Table
461 3390 : void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
462 : v8::Isolate* isolate = args.GetIsolate();
463 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
464 1290 : HandleScope scope(isolate);
465 810 : ErrorThrower thrower(i_isolate, "WebAssembly.Module()");
466 2535 : if (args.Length() < 1 || !args[0]->IsObject()) {
467 105 : thrower.TypeError("Argument 0 must be a table descriptor");
468 105 : return;
469 : }
470 1185 : Local<Context> context = isolate->GetCurrentContext();
471 1185 : Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
472 : // The descriptor's 'element'.
473 : {
474 : v8::MaybeLocal<v8::Value> maybe =
475 1185 : descriptor->Get(context, v8_str(isolate, "element"));
476 : v8::Local<v8::Value> value;
477 1335 : if (!maybe.ToLocal(&value)) return;
478 : v8::Local<v8::String> string;
479 2370 : if (!value->ToString(context).ToLocal(&string)) return;
480 : bool equal;
481 2370 : if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return;
482 1185 : if (!equal) {
483 150 : thrower.TypeError("Descriptor property 'element' must be 'anyfunc'");
484 150 : return;
485 : }
486 : }
487 : // The descriptor's 'initial'.
488 1035 : int initial = 0;
489 1035 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
490 : v8_str(isolate, "initial"), &initial, 0,
491 2070 : i::FLAG_wasm_max_table_size)) {
492 : return;
493 : }
494 : // The descriptor's 'maximum'.
495 915 : int maximum = -1;
496 : Local<String> maximum_key = v8_str(isolate, "maximum");
497 915 : Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
498 :
499 1830 : if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
500 510 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
501 : &maximum, initial,
502 510 : i::wasm::kSpecMaxWasmTableSize)) {
503 : return;
504 : }
505 : }
506 :
507 : i::Handle<i::FixedArray> fixed_array;
508 : i::Handle<i::JSObject> table_obj =
509 810 : i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array);
510 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
511 810 : return_value.Set(Utils::ToLocal(table_obj));
512 : }
513 :
514 3000 : void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
515 : v8::Isolate* isolate = args.GetIsolate();
516 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
517 1125 : HandleScope scope(isolate);
518 750 : ErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
519 2205 : if (args.Length() < 1 || !args[0]->IsObject()) {
520 105 : thrower.TypeError("Argument 0 must be a memory descriptor");
521 105 : return;
522 : }
523 1020 : Local<Context> context = isolate->GetCurrentContext();
524 1020 : Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
525 : // The descriptor's 'initial'.
526 1020 : int initial = 0;
527 1020 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
528 : v8_str(isolate, "initial"), &initial, 0,
529 2040 : i::FLAG_wasm_max_mem_pages)) {
530 : return;
531 : }
532 : // The descriptor's 'maximum'.
533 885 : int maximum = -1;
534 : Local<String> maximum_key = v8_str(isolate, "maximum");
535 885 : Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
536 :
537 1770 : if (!has_maximum.IsNothing() && has_maximum.FromJust()) {
538 375 : if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key,
539 : &maximum, initial,
540 375 : i::wasm::kSpecMaxWasmMemoryPages)) {
541 : return;
542 : }
543 : }
544 750 : size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) *
545 750 : static_cast<size_t>(initial);
546 : i::Handle<i::JSArrayBuffer> buffer =
547 750 : i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages);
548 750 : if (buffer.is_null()) {
549 0 : thrower.RangeError("could not allocate memory");
550 0 : return;
551 : }
552 : i::Handle<i::JSObject> memory_obj =
553 750 : i::WasmMemoryObject::New(i_isolate, buffer, maximum);
554 750 : args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
555 : }
556 :
557 4812 : void WebAssemblyTableGetLength(
558 19014 : const v8::FunctionCallbackInfo<v8::Value>& args) {
559 : v8::Isolate* isolate = args.GetIsolate();
560 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
561 4812 : HandleScope scope(isolate);
562 4695 : ErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
563 4812 : Local<Context> context = isolate->GetCurrentContext();
564 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
565 4812 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
566 : i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
567 4812 : "Receiver is not a WebAssembly.Table")) {
568 117 : return;
569 : }
570 : auto receiver =
571 : i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
572 : args.GetReturnValue().Set(
573 9390 : v8::Number::New(isolate, receiver->current_length()));
574 : }
575 :
576 : // WebAssembly.Table.grow(num) -> num
577 2205 : void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
578 : v8::Isolate* isolate = args.GetIsolate();
579 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
580 525 : HandleScope scope(isolate);
581 255 : ErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
582 525 : Local<Context> context = isolate->GetCurrentContext();
583 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
584 525 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
585 : i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
586 525 : "Receiver is not a WebAssembly.Table")) {
587 270 : return;
588 : }
589 :
590 : auto receiver =
591 : i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
592 450 : i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate);
593 : int old_size = old_array->length();
594 : int64_t new_size64 = 0;
595 1350 : if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) {
596 : return;
597 : }
598 450 : new_size64 += old_size;
599 :
600 450 : int64_t max_size64 = receiver->maximum_length();
601 795 : if (max_size64 < 0 ||
602 345 : max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) {
603 105 : max_size64 = i::FLAG_wasm_max_table_size;
604 : }
605 :
606 450 : if (new_size64 < old_size || new_size64 > max_size64) {
607 : thrower.RangeError(new_size64 < old_size ? "trying to shrink table"
608 195 : : "maximum table size exceeded");
609 195 : return;
610 : }
611 :
612 255 : int new_size = static_cast<int>(new_size64);
613 : i::WasmTableObject::Grow(i_isolate, receiver,
614 255 : static_cast<uint32_t>(new_size - old_size));
615 :
616 255 : if (new_size != old_size) {
617 : i::Handle<i::FixedArray> new_array =
618 180 : i_isolate->factory()->NewFixedArray(new_size);
619 2160 : for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i));
620 180 : i::Object* null = i_isolate->heap()->null_value();
621 150001035 : for (int i = old_size; i < new_size; ++i) new_array->set(i, null);
622 180 : receiver->set_functions(*new_array);
623 : }
624 :
625 : // TODO(gdeepti): use weak links for instances
626 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
627 255 : return_value.Set(old_size);
628 : }
629 :
630 : // WebAssembly.Table.get(num) -> JSFunction
631 58395 : void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
632 : v8::Isolate* isolate = args.GetIsolate();
633 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
634 11730 : HandleScope scope(isolate);
635 11400 : ErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
636 11730 : Local<Context> context = isolate->GetCurrentContext();
637 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
638 11730 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
639 : i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
640 11730 : "Receiver is not a WebAssembly.Table")) {
641 330 : return;
642 : }
643 :
644 : auto receiver =
645 : i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
646 11655 : i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
647 : int i = 0;
648 34965 : if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return;
649 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
650 23205 : if (i < 0 || i >= array->length()) {
651 225 : thrower.RangeError("index out of bounds");
652 225 : return;
653 : }
654 :
655 : i::Handle<i::Object> value(array->get(i), i_isolate);
656 11400 : return_value.Set(Utils::ToLocal(value));
657 : }
658 :
659 : // WebAssembly.Table.set(num, JSFunction)
660 16320 : void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
661 : v8::Isolate* isolate = args.GetIsolate();
662 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
663 4200 : HandleScope scope(isolate);
664 3480 : ErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
665 4200 : Local<Context> context = isolate->GetCurrentContext();
666 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
667 4200 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
668 : i::Handle<i::Symbol>(i_context->wasm_table_sym()), &thrower,
669 4200 : "Receiver is not a WebAssembly.Table")) {
670 720 : return;
671 : }
672 4110 : if (args.Length() < 2) {
673 60 : thrower.TypeError("Argument 1 must be null or a function");
674 60 : return;
675 : }
676 : i::Handle<i::Object> value = Utils::OpenHandle(*args[1]);
677 9690 : if (!value->IsNull(i_isolate) &&
678 1410 : (!value->IsJSFunction() ||
679 : i::Handle<i::JSFunction>::cast(value)->code()->kind() !=
680 : i::Code::JS_TO_WASM_FUNCTION)) {
681 240 : thrower.TypeError("Argument 1 must be null or a WebAssembly function");
682 240 : return;
683 : }
684 :
685 : auto receiver =
686 : i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
687 3810 : i::Handle<i::FixedArray> array(receiver->functions(), i_isolate);
688 : int i;
689 7620 : if (!args[0]->Int32Value(context).To(&i)) return;
690 7470 : if (i < 0 || i >= array->length()) {
691 285 : thrower.RangeError("index out of bounds");
692 285 : return;
693 : }
694 :
695 : i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(),
696 3480 : i_isolate);
697 3480 : if (value->IsNull(i_isolate)) {
698 : i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
699 2250 : i::Handle<i::JSFunction>::null());
700 : } else {
701 : i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
702 1230 : i::Handle<i::JSFunction>::cast(value));
703 : }
704 :
705 6960 : i::Handle<i::FixedArray>::cast(array)->set(i, *value);
706 : }
707 :
708 : // WebAssembly.Memory.grow(num) -> num
709 2940 : void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
710 : v8::Isolate* isolate = args.GetIsolate();
711 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
712 660 : HandleScope scope(isolate);
713 420 : ErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
714 660 : Local<Context> context = isolate->GetCurrentContext();
715 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
716 660 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
717 : i::Handle<i::Symbol>(i_context->wasm_memory_sym()), &thrower,
718 660 : "Receiver is not a WebAssembly.Memory")) {
719 240 : return;
720 : }
721 : int64_t delta_size = 0;
722 1800 : if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) {
723 0 : thrower.TypeError("Argument 0 required, must be numeric value of pages");
724 0 : return;
725 : }
726 : i::Handle<i::WasmMemoryObject> receiver =
727 : i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This()));
728 600 : int64_t max_size64 = receiver->maximum_pages();
729 1050 : if (max_size64 < 0 ||
730 450 : max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) {
731 150 : max_size64 = i::FLAG_wasm_max_mem_pages;
732 : }
733 600 : i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer());
734 : uint32_t old_size =
735 600 : old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages;
736 600 : int64_t new_size64 = old_size + delta_size;
737 600 : if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) {
738 : thrower.RangeError(new_size64 < old_size ? "trying to shrink memory"
739 180 : : "maximum memory size exceeded");
740 180 : return;
741 : }
742 : int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver,
743 420 : static_cast<uint32_t>(delta_size));
744 420 : if (ret == -1) {
745 0 : thrower.RangeError("Unable to grow instance memory.");
746 0 : return;
747 : }
748 420 : i::wasm::DetachWebAssemblyMemoryBuffer(i_isolate, old_buffer);
749 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
750 420 : return_value.Set(ret);
751 : }
752 :
753 : // WebAssembly.Memory.buffer -> ArrayBuffer
754 2817 : void WebAssemblyMemoryGetBuffer(
755 11034 : const v8::FunctionCallbackInfo<v8::Value>& args) {
756 : v8::Isolate* isolate = args.GetIsolate();
757 : i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
758 2817 : HandleScope scope(isolate);
759 2700 : ErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
760 2817 : Local<Context> context = isolate->GetCurrentContext();
761 : i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
762 2817 : if (!BrandCheck(Utils::OpenHandle(*args.This()),
763 : i::Handle<i::Symbol>(i_context->wasm_memory_sym()), &thrower,
764 2817 : "Receiver is not a WebAssembly.Memory")) {
765 117 : return;
766 : }
767 : i::Handle<i::WasmMemoryObject> receiver =
768 : i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This()));
769 2700 : i::Handle<i::Object> buffer(receiver->buffer(), i_isolate);
770 : DCHECK(buffer->IsJSArrayBuffer());
771 : v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
772 2700 : return_value.Set(Utils::ToLocal(buffer));
773 : }
774 : } // namespace
775 :
776 : // TODO(titzer): we use the API to create the function template because the
777 : // internal guts are too ugly to replicate here.
778 1686126 : static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
779 : FunctionCallback func) {
780 : Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
781 1686126 : Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
782 1686128 : templ->ReadOnlyPrototype();
783 1686127 : return v8::Utils::OpenHandle(*templ);
784 : }
785 :
786 : namespace internal {
787 :
788 1475357 : Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
789 : const char* str, FunctionCallback func,
790 : int length = 0) {
791 : Handle<String> name = v8_str(isolate, str);
792 1475360 : Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
793 : Handle<JSFunction> function =
794 2950719 : ApiNatives::InstantiateFunction(temp).ToHandleChecked();
795 1475358 : JSFunction::SetName(function, name, isolate->factory()->empty_string());
796 : function->shared()->set_length(length);
797 : PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
798 1475359 : JSObject::AddProperty(object, name, function, attributes);
799 1475361 : return function;
800 : }
801 :
802 210766 : Handle<JSFunction> InstallGetter(Isolate* isolate, Handle<JSObject> object,
803 : const char* str, FunctionCallback func) {
804 : Handle<String> name = v8_str(isolate, str);
805 210766 : Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
806 : Handle<JSFunction> function =
807 421532 : ApiNatives::InstantiateFunction(temp).ToHandleChecked();
808 : v8::PropertyAttribute attributes =
809 : static_cast<v8::PropertyAttribute>(v8::DontEnum);
810 : Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
811 : Utils::ToLocal(function),
812 210766 : Local<Function>(), attributes);
813 210766 : return function;
814 : }
815 :
816 146805 : void WasmJs::Install(Isolate* isolate) {
817 146805 : Handle<JSGlobalObject> global = isolate->global_object();
818 : Handle<Context> context(global->native_context(), isolate);
819 : // TODO(titzer): once FLAG_expose_wasm is gone, this should become a DCHECK.
820 188229 : if (context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) return;
821 :
822 : // Install Maps.
823 :
824 : // TODO(titzer): Also make one for strict mode functions?
825 : Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
826 :
827 : InstanceType instance_type = prev_map->instance_type();
828 105383 : int embedder_fields = JSObject::GetEmbedderFieldCount(*prev_map);
829 105383 : CHECK_EQ(0, embedder_fields);
830 : int pre_allocated =
831 105383 : prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
832 105383 : int instance_size = 0;
833 105383 : int in_object_properties = 0;
834 : int wasm_embedder_fields = embedder_fields + 1 // module instance object
835 : + 1 // function arity
836 105383 : + 1; // function signature
837 : JSFunction::CalculateInstanceSizeHelper(instance_type, wasm_embedder_fields,
838 : 0, &instance_size,
839 105383 : &in_object_properties);
840 :
841 105383 : int unused_property_fields = in_object_properties - pre_allocated;
842 : Handle<Map> map = Map::CopyInitialMap(
843 105383 : prev_map, instance_size, in_object_properties, unused_property_fields);
844 :
845 : context->set_wasm_function_map(*map);
846 :
847 : // Install symbols.
848 :
849 : Factory* factory = isolate->factory();
850 : // Create private symbols.
851 105383 : Handle<Symbol> module_sym = factory->NewPrivateSymbol();
852 : context->set_wasm_module_sym(*module_sym);
853 :
854 105382 : Handle<Symbol> instance_sym = factory->NewPrivateSymbol();
855 : context->set_wasm_instance_sym(*instance_sym);
856 :
857 105383 : Handle<Symbol> table_sym = factory->NewPrivateSymbol();
858 : context->set_wasm_table_sym(*table_sym);
859 :
860 105383 : Handle<Symbol> memory_sym = factory->NewPrivateSymbol();
861 : context->set_wasm_memory_sym(*memory_sym);
862 :
863 : // Install the JS API.
864 :
865 : // Setup WebAssembly
866 : Handle<String> name = v8_str(isolate, "WebAssembly");
867 105383 : Handle<JSFunction> cons = factory->NewFunction(name);
868 210766 : JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
869 105382 : cons->shared()->set_instance_class_name(*name);
870 105382 : Handle<JSObject> webassembly = factory->NewJSObject(cons, TENURED);
871 : PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
872 105383 : JSObject::AddProperty(global, name, webassembly, attributes);
873 : PropertyAttributes ro_attributes =
874 : static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
875 : JSObject::AddProperty(webassembly, factory->to_string_tag_symbol(),
876 105383 : v8_str(isolate, "WebAssembly"), ro_attributes);
877 105382 : InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
878 105382 : InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
879 105383 : InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
880 :
881 : // Setup Module
882 : Handle<JSFunction> module_constructor =
883 105383 : InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
884 : context->set_wasm_module_constructor(*module_constructor);
885 : Handle<JSObject> module_proto =
886 105382 : factory->NewJSObject(module_constructor, TENURED);
887 : i::Handle<i::Map> module_map = isolate->factory()->NewMap(
888 : i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
889 105383 : WasmModuleObject::kFieldCount * i::kPointerSize);
890 105383 : JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
891 : InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
892 105383 : 1);
893 : InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
894 105383 : 1);
895 : InstallFunc(isolate, module_constructor, "customSections",
896 105383 : WebAssemblyModuleCustomSections, 2);
897 : JSObject::AddProperty(module_proto, isolate->factory()->constructor_string(),
898 105383 : module_constructor, DONT_ENUM);
899 : JSObject::AddProperty(module_proto, factory->to_string_tag_symbol(),
900 105383 : v8_str(isolate, "WebAssembly.Module"), ro_attributes);
901 :
902 : // Setup Instance
903 : Handle<JSFunction> instance_constructor =
904 105383 : InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
905 : context->set_wasm_instance_constructor(*instance_constructor);
906 : Handle<JSObject> instance_proto =
907 105383 : factory->NewJSObject(instance_constructor, TENURED);
908 : i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
909 : i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
910 105383 : WasmInstanceObject::kFieldCount * i::kPointerSize);
911 105383 : JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
912 : JSObject::AddProperty(instance_proto,
913 : isolate->factory()->constructor_string(),
914 105383 : instance_constructor, DONT_ENUM);
915 : JSObject::AddProperty(instance_proto, factory->to_string_tag_symbol(),
916 105383 : v8_str(isolate, "WebAssembly.Instance"), ro_attributes);
917 :
918 : // Setup Table
919 : Handle<JSFunction> table_constructor =
920 105383 : InstallFunc(isolate, webassembly, "Table", WebAssemblyTable, 1);
921 : context->set_wasm_table_constructor(*table_constructor);
922 : Handle<JSObject> table_proto =
923 105383 : factory->NewJSObject(table_constructor, TENURED);
924 : i::Handle<i::Map> table_map = isolate->factory()->NewMap(
925 : i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
926 105383 : WasmTableObject::kFieldCount * i::kPointerSize);
927 105383 : JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
928 : JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(),
929 105383 : table_constructor, DONT_ENUM);
930 105383 : InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
931 105383 : InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
932 105383 : InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
933 105383 : InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
934 : JSObject::AddProperty(table_proto, factory->to_string_tag_symbol(),
935 105383 : v8_str(isolate, "WebAssembly.Table"), ro_attributes);
936 :
937 : // Setup Memory
938 : Handle<JSFunction> memory_constructor =
939 105382 : InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory, 1);
940 : context->set_wasm_memory_constructor(*memory_constructor);
941 : Handle<JSObject> memory_proto =
942 105382 : factory->NewJSObject(memory_constructor, TENURED);
943 : i::Handle<i::Map> memory_map = isolate->factory()->NewMap(
944 : i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
945 105383 : WasmMemoryObject::kFieldCount * i::kPointerSize);
946 105382 : JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
947 : JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(),
948 105383 : memory_constructor, DONT_ENUM);
949 105383 : InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
950 105383 : InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
951 : JSObject::AddProperty(memory_proto, factory->to_string_tag_symbol(),
952 105383 : v8_str(isolate, "WebAssembly.Memory"), ro_attributes);
953 :
954 : // Setup errors
955 : attributes = static_cast<PropertyAttributes>(DONT_ENUM);
956 : Handle<JSFunction> compile_error(
957 210765 : isolate->native_context()->wasm_compile_error_function());
958 : JSObject::AddProperty(webassembly, isolate->factory()->CompileError_string(),
959 105383 : compile_error, attributes);
960 : Handle<JSFunction> link_error(
961 210765 : isolate->native_context()->wasm_link_error_function());
962 : JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(),
963 105383 : link_error, attributes);
964 : Handle<JSFunction> runtime_error(
965 210766 : isolate->native_context()->wasm_runtime_error_function());
966 : JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(),
967 105383 : runtime_error, attributes);
968 : }
969 :
970 1035 : bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) {
971 : i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
972 1035 : return HasBrand(value, symbol);
973 : }
974 :
975 765 : bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
976 : i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
977 765 : return HasBrand(value, symbol);
978 : }
979 : } // namespace internal
980 : } // namespace v8
|