Chromium Code Reviews| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 return_value.Set(v8::False(isolate)); | 173 return_value.Set(v8::False(isolate)); |
| 163 } | 174 } |
| 164 } | 175 } |
| 165 | 176 |
| 166 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 177 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 167 v8::Isolate* isolate = args.GetIsolate(); | 178 v8::Isolate* isolate = args.GetIsolate(); |
| 168 HandleScope scope(isolate); | 179 HandleScope scope(isolate); |
| 169 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 180 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 170 "WebAssembly.Module()"); | 181 "WebAssembly.Module()"); |
| 171 | 182 |
| 172 if (args.Length() < 1) { | 183 if (args.Length() != 1) { |
|
rossberg
2017/01/20 09:56:54
JavaScript always allows unused extra arguments, s
Mircea Trofin
2017/01/20 16:29:53
Done.
| |
| 173 thrower.TypeError("Argument 0 must be a buffer source"); | 184 thrower.TypeError("Argument 0 must be a buffer source"); |
| 174 return; | 185 return; |
| 175 } | 186 } |
| 176 | 187 |
| 177 if (args.Length() > 2) { | |
| 178 thrower.LinkError( | |
| 179 "WebAssembly.instantiate accepts no more than 2 parameters"); | |
| 180 return; | |
| 181 } | |
| 182 i::MaybeHandle<i::JSObject> module_obj = | 188 i::MaybeHandle<i::JSObject> module_obj = |
| 183 CreateModuleObject(isolate, args[0], &thrower); | 189 CreateModuleObject(isolate, args[0], &thrower); |
| 184 if (module_obj.is_null()) return; | 190 if (module_obj.is_null()) return; |
| 185 | 191 |
| 186 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 192 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 187 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 193 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
| 188 } | 194 } |
| 189 | 195 |
| 190 MaybeLocal<Value> InstantiateModuleImpl( | 196 MaybeLocal<Value> InstantiateModuleImpl( |
| 191 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, | 197 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 } | 324 } |
| 319 | 325 |
| 320 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 326 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 321 v8::Isolate* isolate = args.GetIsolate(); | 327 v8::Isolate* isolate = args.GetIsolate(); |
| 322 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 328 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 323 | 329 |
| 324 HandleScope scope(isolate); | 330 HandleScope scope(isolate); |
| 325 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); | 331 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); |
| 326 | 332 |
| 327 Local<Context> context = isolate->GetCurrentContext(); | 333 Local<Context> context = isolate->GetCurrentContext(); |
| 334 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | |
| 335 | |
| 328 v8::Local<v8::Promise::Resolver> resolver; | 336 v8::Local<v8::Promise::Resolver> resolver; |
| 329 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 337 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
| 330 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 338 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 331 return_value.Set(resolver->GetPromise()); | 339 return_value.Set(resolver->GetPromise()); |
| 332 | 340 |
| 333 if (args.Length() < 1) { | 341 if (args.Length() < 1) { |
| 334 thrower.TypeError("Argument 0 must be a buffer source"); | 342 thrower.TypeError( |
| 343 "Argument 0 must be provided and must be either a buffer source or a " | |
| 344 "WebAssembly.Module object"); | |
| 335 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 345 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 336 return; | 346 return; |
| 337 } | 347 } |
| 338 | 348 |
| 339 i::MaybeHandle<i::WasmModuleObject> module_obj = | 349 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
| 340 CreateModuleObject(isolate, args[0], &thrower); | 350 if (!first_arg->IsJSObject()) { |
| 341 if (module_obj.is_null()) { | 351 thrower.TypeError( |
| 342 DCHECK(thrower.error()); | 352 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
| 343 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 353 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 344 return; | 354 return; |
| 345 } | 355 } |
| 346 | 356 bool want_pair = !BrandCheck( |
| 347 MaybeLocal<Value> instance = InstantiateModuleImpl( | 357 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
| 348 i_isolate, module_obj.ToHandleChecked(), args, &thrower); | 358 i::Handle<i::WasmModuleObject> module_obj; |
| 359 if (want_pair) { | |
| 360 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = | |
| 361 CreateModuleObject(isolate, args[0], &thrower); | |
| 362 if (!maybe_module_obj.ToHandle(&module_obj)) { | |
| 363 DCHECK(thrower.error()); | |
| 364 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | |
| 365 return; | |
| 366 } | |
| 367 } else { | |
| 368 module_obj = i::Handle<i::WasmModuleObject>::cast(first_arg); | |
| 369 } | |
| 370 DCHECK(!module_obj.is_null()); | |
| 371 MaybeLocal<Value> instance = | |
| 372 InstantiateModuleImpl(i_isolate, module_obj, args, &thrower); | |
| 349 if (instance.IsEmpty()) { | 373 if (instance.IsEmpty()) { |
| 350 DCHECK(thrower.error()); | 374 DCHECK(thrower.error()); |
| 351 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 375 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 352 } else { | 376 } else { |
| 353 DCHECK(!thrower.error()); | 377 DCHECK(!thrower.error()); |
| 354 resolver->Resolve(context, instance.ToLocalChecked()); | 378 Local<Value> retval; |
| 379 if (want_pair) { | |
| 380 i::Handle<i::JSFunction> object_function = i::Handle<i::JSFunction>( | |
| 381 i_isolate->native_context()->object_function(), i_isolate); | |
| 382 | |
| 383 i::Handle<i::JSObject> i_retval = | |
| 384 i_isolate->factory()->NewJSObject(object_function, i::TENURED); | |
| 385 i::Handle<i::String> module_property_name = | |
| 386 i_isolate->factory()->InternalizeUtf8String("module"); | |
| 387 i::Handle<i::String> instance_property_name = | |
| 388 i_isolate->factory()->InternalizeUtf8String("instance"); | |
| 389 i::JSObject::AddProperty(i_retval, module_property_name, module_obj, | |
| 390 i::NONE); | |
| 391 i::JSObject::AddProperty(i_retval, instance_property_name, | |
| 392 Utils::OpenHandle(*instance.ToLocalChecked()), | |
| 393 i::NONE); | |
| 394 retval = Utils::ToLocal(i_retval); | |
| 395 } else { | |
| 396 retval = instance.ToLocalChecked(); | |
| 397 } | |
| 398 DCHECK(!retval.IsEmpty()); | |
| 399 resolver->Resolve(context, retval); | |
| 355 } | 400 } |
| 356 } | 401 } |
| 357 | 402 |
| 358 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 403 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
| 359 Local<Context> context, Local<v8::Object> object, | 404 Local<Context> context, Local<v8::Object> object, |
| 360 Local<String> property, int* result, | 405 Local<String> property, int* result, |
| 361 int64_t lower_bound, uint64_t upper_bound) { | 406 int64_t lower_bound, uint64_t upper_bound) { |
| 362 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 407 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
| 363 v8::Local<v8::Value> value; | 408 v8::Local<v8::Value> value; |
| 364 if (maybe.ToLocal(&value)) { | 409 if (maybe.ToLocal(&value)) { |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 948 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
| 904 return HasBrand(value, symbol); | 949 return HasBrand(value, symbol); |
| 905 } | 950 } |
| 906 | 951 |
| 907 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 952 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
| 908 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 953 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
| 909 return HasBrand(value, symbol); | 954 return HasBrand(value, symbol); |
| 910 } | 955 } |
| 911 } // namespace internal | 956 } // namespace internal |
| 912 } // namespace v8 | 957 } // namespace v8 |
| OLD | NEW |