| 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 13 matching lines...) Expand all Loading... |
| 24 #include "src/wasm/wasm-objects.h" | 24 #include "src/wasm/wasm-objects.h" |
| 25 #include "src/wasm/wasm-result.h" | 25 #include "src/wasm/wasm-result.h" |
| 26 | 26 |
| 27 typedef uint8_t byte; | 27 typedef uint8_t byte; |
| 28 | 28 |
| 29 using v8::internal::wasm::ErrorThrower; | 29 using v8::internal::wasm::ErrorThrower; |
| 30 | 30 |
| 31 namespace v8 { | 31 namespace v8 { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 |
| 35 #define RANGE_ERROR_MSG \ |
| 36 "Wasm compilation exceeds internal limits in this context for the provided " \ |
| 37 "arguments" |
| 38 |
| 34 // TODO(wasm): move brand check to the respective types, and don't throw | 39 // TODO(wasm): move brand check to the respective types, and don't throw |
| 35 // in it, rather, use a provided ErrorThrower, or let caller handle it. | 40 // in it, rather, use a provided ErrorThrower, or let caller handle it. |
| 36 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) { | 41 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) { |
| 37 if (!value->IsJSObject()) return false; | 42 if (!value->IsJSObject()) return false; |
| 38 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 43 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
| 39 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 44 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
| 40 return has_brand.FromMaybe(false); | 45 return has_brand.FromMaybe(false); |
| 41 } | 46 } |
| 42 | 47 |
| 43 static bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym, | 48 static bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 66 i::handle(i_context->wasm_module_sym()), thrower, | 71 i::handle(i_context->wasm_module_sym()), thrower, |
| 67 "Argument 0 must be a WebAssembly.Module")) { | 72 "Argument 0 must be a WebAssembly.Module")) { |
| 68 return {}; | 73 return {}; |
| 69 } | 74 } |
| 70 | 75 |
| 71 Local<Object> module_obj = Local<Object>::Cast(args[0]); | 76 Local<Object> module_obj = Local<Object>::Cast(args[0]); |
| 72 return i::Handle<i::WasmModuleObject>::cast( | 77 return i::Handle<i::WasmModuleObject>::cast( |
| 73 v8::Utils::OpenHandle(*module_obj)); | 78 v8::Utils::OpenHandle(*module_obj)); |
| 74 } | 79 } |
| 75 | 80 |
| 81 bool IsCompilationAllowed(i::Isolate* isolate, ErrorThrower* thrower, |
| 82 v8::Local<v8::Value> source, bool is_async) { |
| 83 // Allow caller to do one final check on thrower state, rather than |
| 84 // one at each step. No information is lost - failure reason is captured |
| 85 // in the thrower state. |
| 86 if (thrower->error()) return false; |
| 87 |
| 88 AllowWasmCompileCallback callback = isolate->allow_wasm_compile_callback(); |
| 89 if (callback != nullptr && |
| 90 !callback(reinterpret_cast<v8::Isolate*>(isolate), source, is_async)) { |
| 91 thrower->RangeError(RANGE_ERROR_MSG); |
| 92 return false; |
| 93 } |
| 94 return true; |
| 95 } |
| 96 |
| 97 bool IsInstantiationAllowed(i::Isolate* isolate, ErrorThrower* thrower, |
| 98 v8::Local<v8::Value> module_or_bytes, |
| 99 i::MaybeHandle<i::JSReceiver> ffi, bool is_async) { |
| 100 // Allow caller to do one final check on thrower state, rather than |
| 101 // one at each step. No information is lost - failure reason is captured |
| 102 // in the thrower state. |
| 103 if (thrower->error()) return false; |
| 104 v8::MaybeLocal<v8::Value> v8_ffi; |
| 105 if (!ffi.is_null()) { |
| 106 v8_ffi = v8::Local<v8::Value>::Cast(Utils::ToLocal(ffi.ToHandleChecked())); |
| 107 } |
| 108 AllowWasmInstantiateCallback callback = |
| 109 isolate->allow_wasm_instantiate_callback(); |
| 110 if (callback != nullptr && |
| 111 !callback(reinterpret_cast<v8::Isolate*>(isolate), module_or_bytes, |
| 112 v8_ffi, is_async)) { |
| 113 thrower->RangeError(RANGE_ERROR_MSG); |
| 114 return false; |
| 115 } |
| 116 return true; |
| 117 } |
| 118 |
| 76 i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( | 119 i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( |
| 77 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { | 120 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { |
| 78 if (args.Length() < 1) { | 121 if (args.Length() < 1) { |
| 79 thrower->TypeError("Argument 0 must be a buffer source"); | 122 thrower->TypeError("Argument 0 must be a buffer source"); |
| 80 return i::wasm::ModuleWireBytes(nullptr, nullptr); | 123 return i::wasm::ModuleWireBytes(nullptr, nullptr); |
| 81 } | 124 } |
| 82 | 125 |
| 83 const byte* start = nullptr; | 126 const byte* start = nullptr; |
| 84 const byte* end = nullptr; | 127 const byte* end = nullptr; |
| 85 v8::Local<v8::Value> source = args[0]; | 128 v8::Local<v8::Value> source = args[0]; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 HandleScope scope(isolate); | 175 HandleScope scope(isolate); |
| 133 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); | 176 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); |
| 134 | 177 |
| 135 Local<Context> context = isolate->GetCurrentContext(); | 178 Local<Context> context = isolate->GetCurrentContext(); |
| 136 v8::Local<v8::Promise::Resolver> resolver; | 179 v8::Local<v8::Promise::Resolver> resolver; |
| 137 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 180 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
| 138 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 181 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 139 return_value.Set(resolver->GetPromise()); | 182 return_value.Set(resolver->GetPromise()); |
| 140 | 183 |
| 141 auto bytes = GetFirstArgumentAsBytes(args, &thrower); | 184 auto bytes = GetFirstArgumentAsBytes(args, &thrower); |
| 142 if (thrower.error()) { | 185 if (!IsCompilationAllowed(i_isolate, &thrower, args[0], true)) { |
| 143 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 186 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 144 return; | 187 return; |
| 145 } | 188 } |
| 189 DCHECK(!thrower.error()); |
| 146 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); | 190 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); |
| 147 i::wasm::AsyncCompile(i_isolate, promise, bytes); | 191 i::wasm::AsyncCompile(i_isolate, promise, bytes); |
| 148 } | 192 } |
| 149 | 193 |
| 150 // WebAssembly.validate(bytes) -> bool | 194 // WebAssembly.validate(bytes) -> bool |
| 151 void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 195 void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 152 v8::Isolate* isolate = args.GetIsolate(); | 196 v8::Isolate* isolate = args.GetIsolate(); |
| 153 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 197 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 154 HandleScope scope(isolate); | 198 HandleScope scope(isolate); |
| 155 ErrorThrower thrower(i_isolate, "WebAssembly.validate()"); | 199 ErrorThrower thrower(i_isolate, "WebAssembly.validate()"); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 168 } | 212 } |
| 169 | 213 |
| 170 // new WebAssembly.Module(bytes) -> WebAssembly.Module | 214 // new WebAssembly.Module(bytes) -> WebAssembly.Module |
| 171 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 215 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 172 v8::Isolate* isolate = args.GetIsolate(); | 216 v8::Isolate* isolate = args.GetIsolate(); |
| 173 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 217 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 174 HandleScope scope(isolate); | 218 HandleScope scope(isolate); |
| 175 ErrorThrower thrower(i_isolate, "WebAssembly.Module()"); | 219 ErrorThrower thrower(i_isolate, "WebAssembly.Module()"); |
| 176 | 220 |
| 177 auto bytes = GetFirstArgumentAsBytes(args, &thrower); | 221 auto bytes = GetFirstArgumentAsBytes(args, &thrower); |
| 178 if (thrower.error()) return; | 222 if (!IsCompilationAllowed(i_isolate, &thrower, args[0], false)) return; |
| 179 | 223 |
| 224 DCHECK(!thrower.error()); |
| 180 i::MaybeHandle<i::Object> module_obj = | 225 i::MaybeHandle<i::Object> module_obj = |
| 181 i::wasm::SyncCompile(i_isolate, &thrower, bytes); | 226 i::wasm::SyncCompile(i_isolate, &thrower, bytes); |
| 182 if (module_obj.is_null()) return; | 227 if (module_obj.is_null()) return; |
| 183 | 228 |
| 184 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 229 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 185 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 230 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
| 186 } | 231 } |
| 187 | 232 |
| 188 // WebAssembly.Module.imports(module) -> Array<Import> | 233 // WebAssembly.Module.imports(module) -> Array<Import> |
| 189 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { | 234 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | 289 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 245 HandleScope scope(args.GetIsolate()); | 290 HandleScope scope(args.GetIsolate()); |
| 246 v8::Isolate* isolate = args.GetIsolate(); | 291 v8::Isolate* isolate = args.GetIsolate(); |
| 247 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 292 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 248 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); | 293 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); |
| 249 | 294 |
| 250 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); | 295 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
| 251 if (thrower.error()) return; | 296 if (thrower.error()) return; |
| 252 | 297 |
| 253 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); | 298 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); |
| 254 if (thrower.error()) return; | 299 if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports, |
| 300 false)) { |
| 301 return; |
| 302 } |
| 303 DCHECK(!thrower.error()); |
| 255 | 304 |
| 256 i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate( | 305 i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate( |
| 257 i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports, | 306 i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports, |
| 258 i::MaybeHandle<i::JSArrayBuffer>()); | 307 i::MaybeHandle<i::JSArrayBuffer>()); |
| 259 if (instance_object.is_null()) return; | 308 if (instance_object.is_null()) return; |
| 260 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked())); | 309 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked())); |
| 261 } | 310 } |
| 262 | 311 |
| 263 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance | 312 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance |
| 264 // WebAssembly.instantiate(bytes, imports) -> | 313 // WebAssembly.instantiate(bytes, imports) -> |
| (...skipping 27 matching lines...) Expand all Loading... |
| 292 "Argument 0 must be a buffer source or a WebAssembly.Module object"); | 341 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
| 293 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 342 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 294 return; | 343 return; |
| 295 } | 344 } |
| 296 | 345 |
| 297 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); | 346 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); |
| 298 if (thrower.error()) { | 347 if (thrower.error()) { |
| 299 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 300 return; | 349 return; |
| 301 } | 350 } |
| 351 if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports, |
| 352 true)) { |
| 353 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 354 return; |
| 355 } |
| 302 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); | 356 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); |
| 303 | |
| 304 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) { | 357 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) { |
| 305 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance | 358 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance |
| 306 auto module_object = GetFirstArgumentAsModule(args, &thrower); | 359 auto module_object = GetFirstArgumentAsModule(args, &thrower); |
| 307 i::wasm::AsyncInstantiate(i_isolate, promise, | 360 i::wasm::AsyncInstantiate(i_isolate, promise, |
| 308 module_object.ToHandleChecked(), maybe_imports); | 361 module_object.ToHandleChecked(), maybe_imports); |
| 309 } else { | 362 } else { |
| 310 // WebAssembly.instantiate(bytes, imports) -> {module, instance} | 363 // WebAssembly.instantiate(bytes, imports) -> {module, instance} |
| 311 auto bytes = GetFirstArgumentAsBytes(args, &thrower); | 364 auto bytes = GetFirstArgumentAsBytes(args, &thrower); |
| 312 if (thrower.error()) { | 365 if (thrower.error()) { |
| 313 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 366 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 912 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
| 860 return HasBrand(value, symbol); | 913 return HasBrand(value, symbol); |
| 861 } | 914 } |
| 862 | 915 |
| 863 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 916 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
| 864 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 917 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
| 865 return HasBrand(value, symbol); | 918 return HasBrand(value, symbol); |
| 866 } | 919 } |
| 867 } // namespace internal | 920 } // namespace internal |
| 868 } // namespace v8 | 921 } // namespace v8 |
| OLD | NEW |