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 |