OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/api-natives.h" | 5 #include "src/api-natives.h" |
6 #include "src/api.h" | 6 #include "src/api.h" |
7 #include "src/asmjs/asm-js.h" | 7 #include "src/asmjs/asm-js.h" |
8 #include "src/asmjs/asm-typer.h" | 8 #include "src/asmjs/asm-typer.h" |
9 #include "src/asmjs/asm-wasm-builder.h" | 9 #include "src/asmjs/asm-wasm-builder.h" |
10 #include "src/assert-scope.h" | 10 #include "src/assert-scope.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 Local<TypedArray> array = Local<TypedArray>::Cast(source); | 61 Local<TypedArray> array = Local<TypedArray>::Cast(source); |
62 Local<ArrayBuffer> buffer = array->Buffer(); | 62 Local<ArrayBuffer> buffer = array->Buffer(); |
63 | 63 |
64 ArrayBuffer::Contents contents = buffer->GetContents(); | 64 ArrayBuffer::Contents contents = buffer->GetContents(); |
65 | 65 |
66 start = | 66 start = |
67 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); | 67 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); |
68 end = start + array->ByteLength(); | 68 end = start + array->ByteLength(); |
69 | 69 |
70 } else { | 70 } else { |
71 thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); | 71 thrower->TypeError("Argument 0 must be a buffer source"); |
72 } | 72 } |
73 if (start == nullptr || end == start) { | 73 if (start == nullptr || end == start) { |
74 thrower->CompileError("BufferSource argument is empty"); | 74 thrower->CompileError("BufferSource argument is empty"); |
75 } | 75 } |
76 return {start, end}; | 76 return {start, end}; |
77 } | 77 } |
78 | 78 |
79 static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject( | 79 static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject( |
80 v8::Isolate* isolate, const v8::Local<v8::Value> source, | 80 v8::Isolate* isolate, const v8::Local<v8::Value> source, |
81 ErrorThrower* thrower) { | 81 ErrorThrower* thrower) { |
(...skipping 17 matching lines...) Expand all Loading... |
99 | 99 |
100 RawBuffer buffer = GetRawBufferSource(source, thrower); | 100 RawBuffer buffer = GetRawBufferSource(source, thrower); |
101 if (buffer.start == nullptr) return false; | 101 if (buffer.start == nullptr) return false; |
102 | 102 |
103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, | 104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, |
105 thrower, | 105 thrower, |
106 i::wasm::ModuleOrigin::kWasmOrigin); | 106 i::wasm::ModuleOrigin::kWasmOrigin); |
107 } | 107 } |
108 | 108 |
| 109 // TODO(wasm): move brand check to the respective types, and don't throw |
| 110 // in it, rather, use a provided ErrorThrower, or let caller handle it. |
| 111 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, |
| 112 i::Handle<i::Symbol> sym) { |
| 113 if (!value->IsJSObject()) return false; |
| 114 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
| 115 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
| 116 if (has_brand.IsNothing()) return false; |
| 117 return has_brand.ToChecked(); |
| 118 } |
| 119 |
109 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 120 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, |
110 i::Handle<i::Symbol> sym, const char* msg) { | 121 i::Handle<i::Symbol> sym, const char* msg) { |
111 if (value->IsJSObject()) { | 122 if (value->IsJSObject()) { |
112 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 123 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
113 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 124 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
114 if (has_brand.IsNothing()) return false; | 125 if (has_brand.IsNothing()) return false; |
115 if (has_brand.ToChecked()) return true; | 126 if (has_brand.ToChecked()) return true; |
116 } | 127 } |
117 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); | 128 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); |
118 isolate->ThrowException(e); | 129 isolate->ThrowException(e); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 v8::Isolate* isolate = args.GetIsolate(); | 181 v8::Isolate* isolate = args.GetIsolate(); |
171 HandleScope scope(isolate); | 182 HandleScope scope(isolate); |
172 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 183 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
173 "WebAssembly.Module()"); | 184 "WebAssembly.Module()"); |
174 | 185 |
175 if (args.Length() < 1) { | 186 if (args.Length() < 1) { |
176 thrower.TypeError("Argument 0 must be a buffer source"); | 187 thrower.TypeError("Argument 0 must be a buffer source"); |
177 return; | 188 return; |
178 } | 189 } |
179 | 190 |
180 if (args.Length() > 2) { | |
181 thrower.LinkError( | |
182 "WebAssembly.instantiate accepts no more than 2 parameters"); | |
183 return; | |
184 } | |
185 i::MaybeHandle<i::JSObject> module_obj = | 191 i::MaybeHandle<i::JSObject> module_obj = |
186 CreateModuleObject(isolate, args[0], &thrower); | 192 CreateModuleObject(isolate, args[0], &thrower); |
187 if (module_obj.is_null()) return; | 193 if (module_obj.is_null()) return; |
188 | 194 |
189 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 195 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
190 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 196 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
191 } | 197 } |
192 | 198 |
193 MaybeLocal<Value> InstantiateModuleImpl( | 199 MaybeLocal<Value> InstantiateModuleImpl( |
194 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, | 200 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 } | 327 } |
322 | 328 |
323 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 329 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
324 v8::Isolate* isolate = args.GetIsolate(); | 330 v8::Isolate* isolate = args.GetIsolate(); |
325 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 331 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
326 | 332 |
327 HandleScope scope(isolate); | 333 HandleScope scope(isolate); |
328 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); | 334 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); |
329 | 335 |
330 Local<Context> context = isolate->GetCurrentContext(); | 336 Local<Context> context = isolate->GetCurrentContext(); |
| 337 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 338 |
331 v8::Local<v8::Promise::Resolver> resolver; | 339 v8::Local<v8::Promise::Resolver> resolver; |
332 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 340 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
333 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 341 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
334 return_value.Set(resolver->GetPromise()); | 342 return_value.Set(resolver->GetPromise()); |
335 | 343 |
336 if (args.Length() < 1) { | 344 if (args.Length() < 1) { |
337 thrower.TypeError("Argument 0 must be a buffer source"); | 345 thrower.TypeError( |
| 346 "Argument 0 must be provided and must be either a buffer source or a " |
| 347 "WebAssembly.Module object"); |
338 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
339 return; | 349 return; |
340 } | 350 } |
341 | 351 |
342 i::MaybeHandle<i::WasmModuleObject> module_obj = | 352 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
343 CreateModuleObject(isolate, args[0], &thrower); | 353 if (!first_arg->IsJSObject()) { |
344 if (module_obj.is_null()) { | 354 thrower.TypeError( |
345 DCHECK(thrower.error()); | 355 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
346 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 356 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
347 return; | 357 return; |
348 } | 358 } |
349 | 359 bool want_pair = !BrandCheck( |
350 MaybeLocal<Value> instance = InstantiateModuleImpl( | 360 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
351 i_isolate, module_obj.ToHandleChecked(), args, &thrower); | 361 i::Handle<i::WasmModuleObject> module_obj; |
| 362 if (want_pair) { |
| 363 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = |
| 364 CreateModuleObject(isolate, args[0], &thrower); |
| 365 if (!maybe_module_obj.ToHandle(&module_obj)) { |
| 366 DCHECK(thrower.error()); |
| 367 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 368 return; |
| 369 } |
| 370 } else { |
| 371 module_obj = i::Handle<i::WasmModuleObject>::cast(first_arg); |
| 372 } |
| 373 DCHECK(!module_obj.is_null()); |
| 374 MaybeLocal<Value> instance = |
| 375 InstantiateModuleImpl(i_isolate, module_obj, args, &thrower); |
352 if (instance.IsEmpty()) { | 376 if (instance.IsEmpty()) { |
353 DCHECK(thrower.error()); | 377 DCHECK(thrower.error()); |
354 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 378 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
355 } else { | 379 } else { |
356 DCHECK(!thrower.error()); | 380 DCHECK(!thrower.error()); |
357 resolver->Resolve(context, instance.ToLocalChecked()); | 381 Local<Value> retval; |
| 382 if (want_pair) { |
| 383 i::Handle<i::JSFunction> object_function = i::Handle<i::JSFunction>( |
| 384 i_isolate->native_context()->object_function(), i_isolate); |
| 385 |
| 386 i::Handle<i::JSObject> i_retval = |
| 387 i_isolate->factory()->NewJSObject(object_function, i::TENURED); |
| 388 i::Handle<i::String> module_property_name = |
| 389 i_isolate->factory()->InternalizeUtf8String("module"); |
| 390 i::Handle<i::String> instance_property_name = |
| 391 i_isolate->factory()->InternalizeUtf8String("instance"); |
| 392 i::JSObject::AddProperty(i_retval, module_property_name, module_obj, |
| 393 i::NONE); |
| 394 i::JSObject::AddProperty(i_retval, instance_property_name, |
| 395 Utils::OpenHandle(*instance.ToLocalChecked()), |
| 396 i::NONE); |
| 397 retval = Utils::ToLocal(i_retval); |
| 398 } else { |
| 399 retval = instance.ToLocalChecked(); |
| 400 } |
| 401 DCHECK(!retval.IsEmpty()); |
| 402 resolver->Resolve(context, retval); |
358 } | 403 } |
359 } | 404 } |
360 | 405 |
361 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 406 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
362 Local<Context> context, Local<v8::Object> object, | 407 Local<Context> context, Local<v8::Object> object, |
363 Local<String> property, int* result, | 408 Local<String> property, int* result, |
364 int64_t lower_bound, uint64_t upper_bound) { | 409 int64_t lower_bound, uint64_t upper_bound) { |
365 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 410 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
366 v8::Local<v8::Value> value; | 411 v8::Local<v8::Value> value; |
367 if (maybe.ToLocal(&value)) { | 412 if (maybe.ToLocal(&value)) { |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 951 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
907 return HasBrand(value, symbol); | 952 return HasBrand(value, symbol); |
908 } | 953 } |
909 | 954 |
910 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 955 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
911 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 956 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
912 return HasBrand(value, symbol); | 957 return HasBrand(value, symbol); |
913 } | 958 } |
914 } // namespace internal | 959 } // namespace internal |
915 } // namespace v8 | 960 } // namespace v8 |
OLD | NEW |